diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs index 4303c698fed..fcbe9af59c1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs @@ -16,6 +16,7 @@ using Volo.Abp.ObjectMapping; using Volo.Abp.Settings; using Volo.Abp.Timing; +using Volo.Abp.UI.Navigation.Urls; using Volo.Abp.Uow; using Volo.Abp.Users; @@ -125,6 +126,9 @@ protected IStringLocalizer L protected ILogger Logger => _lazyLogger.Value; private Lazy _lazyLogger => new Lazy(() => LoggerFactory?.CreateLogger(GetType().FullName) ?? NullLogger.Instance, true); + protected IAppUrlProvider AppUrlProvider => LazyGetRequiredService(ref _appUrlProvider); + private IAppUrlProvider _appUrlProvider; + protected virtual NoContentResult NoContent() //TODO: Is that true to return empty result like that? { return new NoContentResult(); @@ -165,5 +169,42 @@ protected virtual IStringLocalizer CreateLocalizer() return localizer; } + + protected RedirectResult RedirectSafely(string returnUrl, string returnUrlHash = null) + { + return Redirect(GetRedirectUrl(returnUrl, returnUrlHash)); + } + + protected virtual string GetRedirectUrl(string returnUrl, string returnUrlHash = null) + { + returnUrl = NormalizeReturnUrl(returnUrl); + + if (!returnUrlHash.IsNullOrWhiteSpace()) + { + returnUrl = returnUrl + returnUrlHash; + } + + return returnUrl; + } + + private string NormalizeReturnUrl(string returnUrl) + { + if (returnUrl.IsNullOrEmpty()) + { + return GetAppHomeUrl(); + } + + if (Url.IsLocalUrl(returnUrl) || AppUrlProvider.IsRedirectAllowedUrl(returnUrl)) + { + return returnUrl; + } + + return GetAppHomeUrl(); + } + + protected virtual string GetAppHomeUrl() + { + return "~/"; //TODO: ??? + } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj index 53e3c7f5034..d0806d929df 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj @@ -23,7 +23,7 @@ - + diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs index 61d73cb48be..e5edd9662d1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs @@ -39,6 +39,7 @@ using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.UI; +using Volo.Abp.UI.Navigation; namespace Volo.Abp.AspNetCore.Mvc { @@ -47,7 +48,7 @@ namespace Volo.Abp.AspNetCore.Mvc typeof(AbpLocalizationModule), typeof(AbpApiVersioningAbstractionsModule), typeof(AbpAspNetCoreMvcContractsModule), - typeof(AbpUiModule), + typeof(AbpUiNavigationModule), typeof(AbpGlobalFeaturesModule) )] public class AbpAspNetCoreMvcModule : AbpModule diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs index 645e13b0267..f83353092ec 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs @@ -14,6 +14,7 @@ using Volo.Abp.MultiTenancy; using Volo.Abp.ObjectMapping; using Volo.Abp.Timing; +using Volo.Abp.UI.Navigation.Urls; using Volo.Abp.Uow; using Volo.Abp.Users; @@ -115,6 +116,9 @@ protected IStringLocalizer L } private IStringLocalizer _localizer; + protected IAppUrlProvider AppUrlProvider => LazyGetRequiredService(ref _appUrlProvider); + private IAppUrlProvider _appUrlProvider; + protected Type LocalizationResource { get => _localizationResource; @@ -148,5 +152,42 @@ protected virtual IStringLocalizer CreateLocalizer() return localizer; } + + protected RedirectResult RedirectSafely(string returnUrl, string returnUrlHash = null) + { + return Redirect(GetRedirectUrl(returnUrl, returnUrlHash)); + } + + private string GetRedirectUrl(string returnUrl, string returnUrlHash = null) + { + returnUrl = NormalizeReturnUrl(returnUrl); + + if (!returnUrlHash.IsNullOrWhiteSpace()) + { + returnUrl = returnUrl + returnUrlHash; + } + + return returnUrl; + } + + private string NormalizeReturnUrl(string returnUrl) + { + if (returnUrl.IsNullOrEmpty()) + { + return GetAppHomeUrl(); + } + + if (Url.IsLocalUrl(returnUrl) || AppUrlProvider.IsRedirectAllowedUrl(returnUrl)) + { + return returnUrl; + } + + return GetAppHomeUrl(); + } + + protected virtual string GetAppHomeUrl() + { + return "~/"; + } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Authentication/ChallengeAccountController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Authentication/ChallengeAccountController.cs index 781866232b8..d01bac2e812 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Authentication/ChallengeAccountController.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Authentication/ChallengeAccountController.cs @@ -66,42 +66,5 @@ public async Task FrontChannelLogout(string sid) return NoContent(); } - - protected RedirectResult RedirectSafely(string returnUrl, string returnUrlHash = null) - { - return Redirect(GetRedirectUrl(returnUrl, returnUrlHash)); - } - - private string GetRedirectUrl(string returnUrl, string returnUrlHash = null) - { - returnUrl = NormalizeReturnUrl(returnUrl); - - if (!returnUrlHash.IsNullOrWhiteSpace()) - { - returnUrl = returnUrl + returnUrlHash; - } - - return returnUrl; - } - - private string NormalizeReturnUrl(string returnUrl) - { - if (returnUrl.IsNullOrEmpty()) - { - return GetAppHomeUrl(); - } - - if (Url.IsLocalUrl(returnUrl)) - { - return returnUrl; - } - - return GetAppHomeUrl(); - } - - protected virtual string GetAppHomeUrl() - { - return "~/"; - } } } diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/AppUrlOptions.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/AppUrlOptions.cs index ebfbbedcd5c..79a1afba144 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/AppUrlOptions.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/AppUrlOptions.cs @@ -1,12 +1,17 @@ -namespace Volo.Abp.UI.Navigation.Urls +using System.Collections.Generic; + +namespace Volo.Abp.UI.Navigation.Urls { public class AppUrlOptions { public ApplicationUrlDictionary Applications { get; } + public List RedirectAllowedUrls { get; } + public AppUrlOptions() { Applications = new ApplicationUrlDictionary(); + RedirectAllowedUrls = new List(); } } } diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/AppUrlProvider.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/AppUrlProvider.cs index 912621c4242..c722529eca1 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/AppUrlProvider.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/AppUrlProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; @@ -36,6 +37,11 @@ await GetConfiguredUrl( ); } + public bool IsRedirectAllowedUrl(string url) + { + return Options.RedirectAllowedUrls.Any(url.StartsWith); + } + protected virtual Task GetConfiguredUrl(string appName, string urlName) { var app = Options.Applications[appName]; diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/IAppUrlProvider.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/IAppUrlProvider.cs index 37fe1ea0de6..61b6fc2bac8 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/IAppUrlProvider.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/IAppUrlProvider.cs @@ -6,5 +6,7 @@ namespace Volo.Abp.UI.Navigation.Urls public interface IAppUrlProvider { Task GetUrlAsync([NotNull] string appName, [CanBeNull] string urlName = null); + + bool IsRedirectAllowedUrl(string url); } } diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs index 36564f9af89..3e016c8bb51 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs @@ -25,11 +25,6 @@ protected AccountPageModel() ObjectMapperContext = typeof(AbpAccountWebModule); } - protected virtual RedirectResult RedirectSafely(string returnUrl, string returnUrlHash = null) - { - return Redirect(GetRedirectUrl(returnUrl, returnUrlHash)); - } - protected virtual void CheckIdentityErrors(IdentityResult identityResult) { if (!identityResult.Succeeded) @@ -40,33 +35,6 @@ protected virtual void CheckIdentityErrors(IdentityResult identityResult) //identityResult.CheckErrors(LocalizationManager); //TODO: Get from old Abp } - protected virtual string GetRedirectUrl(string returnUrl, string returnUrlHash = null) - { - returnUrl = NormalizeReturnUrl(returnUrl); - - if (!returnUrlHash.IsNullOrWhiteSpace()) - { - returnUrl = returnUrl + returnUrlHash; - } - - return returnUrl; - } - - protected virtual string NormalizeReturnUrl(string returnUrl) - { - if (returnUrl.IsNullOrEmpty()) - { - return GetAppHomeUrl(); - } - - if (Url.IsLocalUrl(returnUrl)) - { - return returnUrl; - } - - return GetAppHomeUrl(); - } - protected virtual void CheckCurrentTenant(Guid? tenantId) { if (CurrentTenant.Id != tenantId) @@ -74,10 +42,5 @@ protected virtual void CheckCurrentTenant(Guid? tenantId) throw new ApplicationException($"Current tenant is different than given tenant. CurrentTenant.Id: {CurrentTenant.Id}, given tenantId: {tenantId}"); } } - - protected virtual string GetAppHomeUrl() - { - return "~/"; //TODO: ??? - } } } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs index 9551cad3100..39cedbb06ac 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs @@ -77,6 +77,7 @@ private void ConfigureUrls(IConfiguration configuration) Configure(options => { options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"]; + options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"].Split(',')); }); } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/appsettings.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/appsettings.json index e62c32aa0cd..795753ec9de 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/appsettings.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/appsettings.json @@ -1,7 +1,8 @@ { "App": { "SelfUrl": "https://localhost:44305", - "CorsOrigins": "https://*.MyProjectName.com,http://localhost:4200,https://localhost:44307" + "CorsOrigins": "https://*.MyProjectName.com,http://localhost:4200,https://localhost:44307", + "RedirectAllowedUrls": "http://localhost:4200,https://localhost:44307" }, "ConnectionStrings": { "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true" diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs index a5013823ac4..07db333488d 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs @@ -112,6 +112,7 @@ public override void ConfigureServices(ServiceConfigurationContext context) Configure(options => { options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"]; + options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"].Split(',')); }); Configure(options => diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/appsettings.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/appsettings.json index e9152eb6adb..c7101f92edd 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/appsettings.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/appsettings.json @@ -1,7 +1,8 @@ { "App": { "SelfUrl": "https://localhost:44301", - "CorsOrigins": "https://*.MyProjectName.com,http://localhost:4200,https://localhost:44307,https://localhost:44300" + "CorsOrigins": "https://*.MyProjectName.com,http://localhost:4200,https://localhost:44307,https://localhost:44300", + "RedirectAllowedUrls": "http://localhost:4200,https://localhost:44307" }, "ConnectionStrings": { "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true"