From f8c9d7ddb914e23f05951b0a03e56be8dec6e80b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Oct 2020 10:28:19 +0300 Subject: [PATCH 1/8] Enable AbpAutoValidateAntiforgeryTokenAttribute by default. --- .../AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs | 11 +- .../Mvc/AntiForgery/AbpAntiForgeryOptions.cs | 10 +- .../AntiForgery/AbpAntiForgeryPreOptions.cs | 10 ++ ...bpAutoValidateAntiforgeryTokenAttribute.cs | 37 +++++++ ...dateAntiforgeryTokenAuthorizationFilter.cs | 78 ++++++++++++++ .../AbpValidateAntiForgeryTokenAttribute.cs | 37 +++++++ ...dateAntiforgeryTokenAuthorizationFilter.cs | 100 ++++++++++++++++++ ...ltAbpRequestLocalizationOptionsProvider.cs | 1 - 8 files changed, 277 insertions(+), 7 deletions(-) create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryPreOptions.cs create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAttribute.cs create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiForgeryTokenAttribute.cs create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs 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 88a81fa1ecb..f1efac83ceb 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 @@ -22,6 +22,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Localization; using Volo.Abp.ApiVersioning; +using Volo.Abp.AspNetCore.Mvc.AntiForgery; using Volo.Abp.AspNetCore.Mvc.ApiExploring; using Volo.Abp.AspNetCore.Mvc.Conventions; using Volo.Abp.AspNetCore.Mvc.DataAnnotations; @@ -94,7 +95,15 @@ public override void ConfigureServices(ServiceConfigurationContext context) } }); - var mvcCoreBuilder = context.Services.AddMvcCore(); + var antiForgeryPreOptions = context.Services.ExecutePreConfiguredActions(); + + var mvcCoreBuilder = context.Services.AddMvcCore(options => + { + if (antiForgeryPreOptions.AutoValidate) + { + options.Filters.Add(new AbpAutoValidateAntiforgeryTokenAttribute()); + } + }); context.Services.ExecutePreConfiguredActions(mvcCoreBuilder); var abpMvcDataAnnotationsLocalizationOptions = context.Services diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs index 0dc573fd5da..defc794998e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs @@ -9,15 +9,15 @@ public class AbpAntiForgeryOptions public string TokenCookieName { get; set; } /// - /// Get/sets header name to transfer Anti Forgery token from client to the server. - /// Default value: "X-XSRF-TOKEN". + /// Used to find auth cookie when validating Anti Forgery token. + /// Default value: ".AspNet.ApplicationCookie". /// - public string TokenHeaderName { get; set; } + public string AuthorizationCookieName { get; set; } public AbpAntiForgeryOptions() { TokenCookieName = "XSRF-TOKEN"; - TokenHeaderName = "X-XSRF-TOKEN"; + AuthorizationCookieName = ".AspNet.ApplicationCookie"; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryPreOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryPreOptions.cs new file mode 100644 index 00000000000..887153fd1b7 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryPreOptions.cs @@ -0,0 +1,10 @@ +namespace Volo.Abp.AspNetCore.Mvc.AntiForgery +{ + public class AbpAntiForgeryPreOptions + { + /// + /// Default value: true. + /// + public bool AutoValidate { get; set; } = true; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAttribute.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAttribute.cs new file mode 100644 index 00000000000..346d5e9db4f --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAttribute.cs @@ -0,0 +1,37 @@ +using System; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Mvc.AntiForgery +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public class AbpAutoValidateAntiforgeryTokenAttribute : Attribute, IFilterFactory, IOrderedFilter + { + /// + /// Gets the order value for determining the order of execution of filters. Filters execute in + /// ascending numeric value of the property. + /// + /// + /// + /// Filters are executed in a sequence determined by an ascending sort of the property. + /// + /// + /// The default Order for this attribute is 1000 because it must run after any filter which does authentication + /// or login in order to allow them to behave as expected (ie Unauthenticated or Redirect instead of 400). + /// + /// + /// Look at for more detailed info. + /// + /// + public int Order { get; set; } = 1000; + + /// + public bool IsReusable => true; + + /// + public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) + { + return serviceProvider.GetRequiredService(); + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs new file mode 100644 index 00000000000..ba787463904 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs @@ -0,0 +1,78 @@ +using System; +using Microsoft.AspNetCore.Antiforgery; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Mvc.AntiForgery +{ + public class AbpAutoValidateAntiforgeryTokenAuthorizationFilter : AbpValidateAntiforgeryTokenAuthorizationFilter, ITransientDependency + { + private readonly AntiforgeryOptions _antiforgeryOptions; + private readonly IOptionsSnapshot _namedOptionsAccessor; + private readonly AbpAntiForgeryOptions _abpAntiForgeryOptions; + + public AbpAutoValidateAntiforgeryTokenAuthorizationFilter( + IAntiforgery antiforgery, + IOptions antiforgeryOptions, + IOptions abpAntiForgeryOptions, + IOptionsSnapshot namedOptionsAccessor, + ILogger logger) + : base(antiforgery, antiforgeryOptions, abpAntiForgeryOptions, namedOptionsAccessor, logger) + { + _namedOptionsAccessor = namedOptionsAccessor; + _abpAntiForgeryOptions = abpAntiForgeryOptions.Value; + _antiforgeryOptions = antiforgeryOptions.Value; + } + + protected override bool ShouldValidate(AuthorizationFilterContext context) + { + if (!ShouldValidateInternal(context)) + { + return false; + } + + var cookieAuthenticationOptions = _namedOptionsAccessor.Get(_abpAntiForgeryOptions.AuthorizationCookieName); + + //Always perform antiforgery validation when request contains authentication cookie + if (cookieAuthenticationOptions?.Cookie.Name != null && + context.HttpContext.Request.Cookies.ContainsKey(cookieAuthenticationOptions.Cookie.Name)) + { + return true; + } + + //No need to validate if antiforgery cookie is not sent. + //That means the request is sent from a non-browser client. + //See https://github.com/aspnet/Antiforgery/issues/115 + if (!context.HttpContext.Request.Cookies.ContainsKey(_antiforgeryOptions.Cookie.Name)) + { + return false; + } + + // Anything else requires a token. + return true; + } + + private static bool ShouldValidateInternal(AuthorizationFilterContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + var method = context.HttpContext.Request.Method; + if (string.Equals("GET", method, StringComparison.OrdinalIgnoreCase) || + string.Equals("HEAD", method, StringComparison.OrdinalIgnoreCase) || + string.Equals("TRACE", method, StringComparison.OrdinalIgnoreCase) || + string.Equals("OPTIONS", method, StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + // Anything else requires a token. + return true; + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiForgeryTokenAttribute.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiForgeryTokenAttribute.cs new file mode 100644 index 00000000000..853f642b29d --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiForgeryTokenAttribute.cs @@ -0,0 +1,37 @@ +using System; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Mvc.AntiForgery +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public class AbpValidateAntiForgeryTokenAttribute : Attribute, IFilterFactory, IOrderedFilter + { + /// + /// Gets the order value for determining the order of execution of filters. Filters execute in + /// ascending numeric value of the property. + /// + /// + /// + /// Filters are executed in an ordering determined by an ascending sort of the property. + /// + /// + /// The default Order for this attribute is 1000 because it must run after any filter which does authentication + /// or login in order to allow them to behave as expected (ie Unauthenticated or Redirect instead of 400). + /// + /// + /// Look at for more detailed info. + /// + /// + public int Order { get; set; } = 1000; + + /// + public bool IsReusable => true; + + /// + public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) + { + return serviceProvider.GetRequiredService(); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs new file mode 100644 index 00000000000..662f1615950 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs @@ -0,0 +1,100 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Antiforgery; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Volo.Abp.AspNetCore.Mvc.AntiForgery +{ + public class AbpValidateAntiforgeryTokenAuthorizationFilter : IAsyncAuthorizationFilter, IAntiforgeryPolicy + { + private IAntiforgery _antiforgery; + private readonly AntiforgeryOptions _antiforgeryOptions; + private readonly IOptionsSnapshot _namedOptionsAccessor; + private readonly AbpAntiForgeryOptions _abpAntiForgeryOptions; + private readonly ILogger _logger; + + public AbpValidateAntiforgeryTokenAuthorizationFilter( + IAntiforgery antiforgery, + IOptions antiforgeryOptions, + IOptions abpAntiForgeryOptions, + IOptionsSnapshot namedOptionsAccessor, + ILogger logger) + { + _antiforgery = antiforgery; + _antiforgeryOptions = antiforgeryOptions.Value; + _namedOptionsAccessor = namedOptionsAccessor; + _logger = logger; + _abpAntiForgeryOptions = abpAntiForgeryOptions.Value; + } + + public async Task OnAuthorizationAsync(AuthorizationFilterContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (!context.IsEffectivePolicy(this)) + { + _logger.LogInformation("Skipping the execution of current filter as its not the most effective filter implementing the policy " + typeof(IAntiforgeryPolicy)); + return; + } + + if (ShouldValidate(context)) + { + try + { + await _antiforgery.ValidateRequestAsync(context.HttpContext); + } + catch (AntiforgeryValidationException exception) + { + _logger.LogError(exception.Message, exception); + context.Result = new AntiforgeryValidationFailedResult(); + } + } + } + + protected virtual bool ShouldValidate(AuthorizationFilterContext context) + { + if (!ShouldValidateInternal(context)) + { + return false; + } + + var cookieAuthenticationOptions = _namedOptionsAccessor.Get(_abpAntiForgeryOptions.AuthorizationCookieName); + + //Always perform antiforgery validation when request contains authentication cookie + if (cookieAuthenticationOptions?.Cookie.Name != null && + context.HttpContext.Request.Cookies.ContainsKey(cookieAuthenticationOptions.Cookie.Name)) + { + return true; + } + + //No need to validate if antiforgery cookie is not sent. + //That means the request is sent from a non-browser client. + //See https://github.com/aspnet/Antiforgery/issues/115 + if (!context.HttpContext.Request.Cookies.ContainsKey(_antiforgeryOptions.Cookie.Name)) + { + return false; + } + + // Anything else requires a token. + return true; + } + + private static bool ShouldValidateInternal(AuthorizationFilterContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + return true; + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs index 263d0532d0b..001fc6a02d8 100644 --- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs @@ -5,7 +5,6 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Localization; using Microsoft.Extensions.DependencyInjection; using Nito.AsyncEx; From 8c4ecf6af0e5e32de7adfe809a2b9af81e36f832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Oct 2020 10:35:01 +0300 Subject: [PATCH 2/8] Fixed logger injection --- .../AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs | 2 +- .../AbpValidateAntiforgeryTokenAuthorizationFilter.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs index ba787463904..04c3326b154 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs @@ -19,7 +19,7 @@ public AbpAutoValidateAntiforgeryTokenAuthorizationFilter( IOptions antiforgeryOptions, IOptions abpAntiForgeryOptions, IOptionsSnapshot namedOptionsAccessor, - ILogger logger) + ILogger logger) : base(antiforgery, antiforgeryOptions, abpAntiForgeryOptions, namedOptionsAccessor, logger) { _namedOptionsAccessor = namedOptionsAccessor; diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs index 662f1615950..5ff410a9c24 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs @@ -16,14 +16,14 @@ public class AbpValidateAntiforgeryTokenAuthorizationFilter : IAsyncAuthorizatio private readonly AntiforgeryOptions _antiforgeryOptions; private readonly IOptionsSnapshot _namedOptionsAccessor; private readonly AbpAntiForgeryOptions _abpAntiForgeryOptions; - private readonly ILogger _logger; + private readonly ILogger _logger; public AbpValidateAntiforgeryTokenAuthorizationFilter( IAntiforgery antiforgery, IOptions antiforgeryOptions, IOptions abpAntiForgeryOptions, IOptionsSnapshot namedOptionsAccessor, - ILogger logger) + ILogger logger) { _antiforgery = antiforgery; _antiforgeryOptions = antiforgeryOptions.Value; From 73216ee1ef9cd5d739a938bb08b152e36f733160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Oct 2020 11:18:03 +0300 Subject: [PATCH 3/8] Extract service: AbpAntiForgeryAuthCookieNameProvider --- .../AbpAntiForgeryAuthCookieNameProvider.cs | 25 +++++++++++++++++++ .../Mvc/AntiForgery/AbpAntiForgeryOptions.cs | 6 ++--- ...dateAntiforgeryTokenAuthorizationFilter.cs | 22 ++++++++-------- ...dateAntiforgeryTokenAuthorizationFilter.cs | 16 +++++------- 4 files changed, 45 insertions(+), 24 deletions(-) create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryAuthCookieNameProvider.cs diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryAuthCookieNameProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryAuthCookieNameProvider.cs new file mode 100644 index 00000000000..48b71e34aef --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryAuthCookieNameProvider.cs @@ -0,0 +1,25 @@ +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Mvc.AntiForgery +{ + public class AbpAntiForgeryAuthCookieNameProvider : ITransientDependency + { + private readonly IOptionsSnapshot _namedOptionsAccessor; + private readonly AbpAntiForgeryOptions _abpAntiForgeryOptions; + + public AbpAntiForgeryAuthCookieNameProvider( + IOptionsSnapshot namedOptionsAccessor, + IOptions abpAntiForgeryOptions) + { + _namedOptionsAccessor = namedOptionsAccessor; + _abpAntiForgeryOptions = abpAntiForgeryOptions.Value; + } + + public virtual string GetNameOrNull() + { + return _namedOptionsAccessor.Get(_abpAntiForgeryOptions.AuthCookieName)?.Cookie?.Name; + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs index defc794998e..5cfd1cf1e79 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs @@ -10,14 +10,14 @@ public class AbpAntiForgeryOptions /// /// Used to find auth cookie when validating Anti Forgery token. - /// Default value: ".AspNet.ApplicationCookie". + /// Default value: ".AspNetCore.Identity.Application". /// - public string AuthorizationCookieName { get; set; } + public string AuthCookieName { get; set; } public AbpAntiForgeryOptions() { TokenCookieName = "XSRF-TOKEN"; - AuthorizationCookieName = ".AspNet.ApplicationCookie"; + AuthCookieName = ".AspNetCore.Identity.Application"; } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs index 04c3326b154..c0dbcd246a4 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs @@ -1,6 +1,5 @@ using System; using Microsoft.AspNetCore.Antiforgery; -using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -11,19 +10,20 @@ namespace Volo.Abp.AspNetCore.Mvc.AntiForgery public class AbpAutoValidateAntiforgeryTokenAuthorizationFilter : AbpValidateAntiforgeryTokenAuthorizationFilter, ITransientDependency { private readonly AntiforgeryOptions _antiforgeryOptions; - private readonly IOptionsSnapshot _namedOptionsAccessor; - private readonly AbpAntiForgeryOptions _abpAntiForgeryOptions; + private readonly AbpAntiForgeryAuthCookieNameProvider _antiForgeryAuthCookieNameProvider; public AbpAutoValidateAntiforgeryTokenAuthorizationFilter( IAntiforgery antiforgery, IOptions antiforgeryOptions, - IOptions abpAntiForgeryOptions, - IOptionsSnapshot namedOptionsAccessor, + AbpAntiForgeryAuthCookieNameProvider antiForgeryAuthCookieNameProvider, ILogger logger) - : base(antiforgery, antiforgeryOptions, abpAntiForgeryOptions, namedOptionsAccessor, logger) + : base( + antiforgery, + antiforgeryOptions, + antiForgeryAuthCookieNameProvider, + logger) { - _namedOptionsAccessor = namedOptionsAccessor; - _abpAntiForgeryOptions = abpAntiForgeryOptions.Value; + _antiForgeryAuthCookieNameProvider = antiForgeryAuthCookieNameProvider; _antiforgeryOptions = antiforgeryOptions.Value; } @@ -34,11 +34,11 @@ protected override bool ShouldValidate(AuthorizationFilterContext context) return false; } - var cookieAuthenticationOptions = _namedOptionsAccessor.Get(_abpAntiForgeryOptions.AuthorizationCookieName); + var authCookieName = _antiForgeryAuthCookieNameProvider.GetNameOrNull(); //Always perform antiforgery validation when request contains authentication cookie - if (cookieAuthenticationOptions?.Cookie.Name != null && - context.HttpContext.Request.Cookies.ContainsKey(cookieAuthenticationOptions.Cookie.Name)) + if (authCookieName != null && + context.HttpContext.Request.Cookies.ContainsKey(authCookieName)) { return true; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs index 5ff410a9c24..a544de4f17a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs @@ -1,7 +1,6 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Antiforgery; -using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.ViewFeatures; @@ -14,22 +13,19 @@ public class AbpValidateAntiforgeryTokenAuthorizationFilter : IAsyncAuthorizatio { private IAntiforgery _antiforgery; private readonly AntiforgeryOptions _antiforgeryOptions; - private readonly IOptionsSnapshot _namedOptionsAccessor; - private readonly AbpAntiForgeryOptions _abpAntiForgeryOptions; + private readonly AbpAntiForgeryAuthCookieNameProvider _antiForgeryAuthCookieNameProvider; private readonly ILogger _logger; public AbpValidateAntiforgeryTokenAuthorizationFilter( IAntiforgery antiforgery, IOptions antiforgeryOptions, - IOptions abpAntiForgeryOptions, - IOptionsSnapshot namedOptionsAccessor, + AbpAntiForgeryAuthCookieNameProvider antiForgeryAuthCookieNameProvider, ILogger logger) { _antiforgery = antiforgery; _antiforgeryOptions = antiforgeryOptions.Value; - _namedOptionsAccessor = namedOptionsAccessor; _logger = logger; - _abpAntiForgeryOptions = abpAntiForgeryOptions.Value; + _antiForgeryAuthCookieNameProvider = antiForgeryAuthCookieNameProvider; } public async Task OnAuthorizationAsync(AuthorizationFilterContext context) @@ -66,11 +62,11 @@ protected virtual bool ShouldValidate(AuthorizationFilterContext context) return false; } - var cookieAuthenticationOptions = _namedOptionsAccessor.Get(_abpAntiForgeryOptions.AuthorizationCookieName); + var authCookieName = _antiForgeryAuthCookieNameProvider.GetNameOrNull(); //Always perform antiforgery validation when request contains authentication cookie - if (cookieAuthenticationOptions?.Cookie.Name != null && - context.HttpContext.Request.Cookies.ContainsKey(cookieAuthenticationOptions.Cookie.Name)) + if (authCookieName != null && + context.HttpContext.Request.Cookies.ContainsKey(authCookieName)) { return true; } From 104244a05d21e632233f17c7d7387e9d437f55bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Oct 2020 14:27:41 +0300 Subject: [PATCH 4/8] Auto set antiforgery cookie --- .../Themes/Basic/Layouts/Account.cshtml | 2 -- .../Themes/Basic/Layouts/Application.cshtml | 2 -- .../Themes/Basic/Layouts/Empty.cshtml | 2 -- .../AbpAntiForgeryAuthCookieNameProvider.cs | 2 +- ...pAntiForgeryManagerAspNetCoreExtensions.cs | 8 ++++-- .../Mvc/AntiForgery/AbpAntiForgeryOptions.cs | 26 +++++++++++++------ ...dateAntiforgeryTokenAuthorizationFilter.cs | 3 ++- .../AspNetCoreAbpAntiForgeryManager.cs | 8 ++++-- .../AbpApplicationConfigurationController.cs | 9 +++++-- ...pplicationConfigurationScriptController.cs | 8 +++++- 10 files changed, 47 insertions(+), 23 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml index 5fcd5951cd3..6ab5267b728 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml @@ -13,7 +13,6 @@ @using Volo.Abp.AspNetCore.Mvc.UI.Widgets.Components.WidgetStyles @using Volo.Abp.MultiTenancy @using Volo.Abp.Localization -@inject IAbpAntiForgeryManager AbpAntiForgeryManager @inject IBrandingProvider BrandingProvider @inject IOptions MultiTenancyOptions @inject ICurrentTenant CurrentTenant @@ -22,7 +21,6 @@ @{ Layout = null; - AbpAntiForgeryManager.SetCookie(); var containerClass = ViewBag.FluidLayout == true ? "container-fluid" : "container"; //TODO: Better and type-safe options var rtl = CultureHelper.IsRtl ? "rtl" : string.Empty; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml index 7b06538510d..d3ebd2f57f1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml @@ -9,12 +9,10 @@ @using Volo.Abp.AspNetCore.Mvc.UI.Widgets.Components.WidgetScripts @using Volo.Abp.AspNetCore.Mvc.UI.Widgets.Components.WidgetStyles @using Volo.Abp.Localization -@inject IAbpAntiForgeryManager AbpAntiForgeryManager @inject IBrandingProvider BrandingProvider @inject IPageLayout PageLayout @{ Layout = null; - AbpAntiForgeryManager.SetCookie(); var containerClass = ViewBag.FluidLayout == true ? "container-fluid" : "container"; //TODO: Better and type-safe options var pageTitle = ViewBag.Title == null ? BrandingProvider.AppName : ViewBag.Title; //TODO: Discard to get from Title diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Empty.cshtml b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Empty.cshtml index 9871bcbb258..2176782a70d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Empty.cshtml +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Empty.cshtml @@ -8,12 +8,10 @@ @using Volo.Abp.AspNetCore.Mvc.UI.Widgets.Components.WidgetScripts @using Volo.Abp.AspNetCore.Mvc.UI.Widgets.Components.WidgetStyles @using Volo.Abp.Localization -@inject IAbpAntiForgeryManager AbpAntiForgeryManager @inject IBrandingProvider BrandingProvider @inject IPageLayout PageLayout @{ Layout = null; - AbpAntiForgeryManager.SetCookie(); var containerClass = ViewBag.FluidLayout == true ? "container-fluid" : "container"; //TODO: Better and type-safe options var pageTitle = ViewBag.Title == null ? BrandingProvider.AppName : ViewBag.Title; //TODO: Discard to get from Title diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryAuthCookieNameProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryAuthCookieNameProvider.cs index 48b71e34aef..6cd18c82a47 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryAuthCookieNameProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryAuthCookieNameProvider.cs @@ -19,7 +19,7 @@ public AbpAntiForgeryAuthCookieNameProvider( public virtual string GetNameOrNull() { - return _namedOptionsAccessor.Get(_abpAntiForgeryOptions.AuthCookieName)?.Cookie?.Name; + return _namedOptionsAccessor.Get(_abpAntiForgeryOptions.AuthCookieSchemaName)?.Cookie?.Name; } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryManagerAspNetCoreExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryManagerAspNetCoreExtensions.cs index c5c992b3642..31ea869b06a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryManagerAspNetCoreExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryManagerAspNetCoreExtensions.cs @@ -4,7 +4,11 @@ public static class AbpAntiForgeryManagerAspNetCoreExtensions { public static void SetCookie(this IAbpAntiForgeryManager manager) { - manager.HttpContext.Response.Cookies.Append(manager.Options.TokenCookieName, manager.GenerateToken()); + manager.HttpContext.Response.Cookies.Append( + manager.Options.TokenCookie.Name, + manager.GenerateToken(), + manager.Options.TokenCookie.Build(manager.HttpContext) + ); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs index 5cfd1cf1e79..1e21482981d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs @@ -1,23 +1,33 @@ -namespace Volo.Abp.AspNetCore.Mvc.AntiForgery +using System; +using Microsoft.AspNetCore.Http; + +namespace Volo.Abp.AspNetCore.Mvc.AntiForgery { public class AbpAntiForgeryOptions { /// - /// Get/sets cookie name to transfer Anti Forgery token between server and client. - /// Default value: "XSRF-TOKEN". + /// Use to set the cookie options to transfer Anti Forgery token between server and client. + /// Default name of the cookie: "XSRF-TOKEN". /// - public string TokenCookieName { get; set; } + public CookieBuilder TokenCookie { get; } /// /// Used to find auth cookie when validating Anti Forgery token. - /// Default value: ".AspNetCore.Identity.Application". + /// Default value: "Identity.Application". /// - public string AuthCookieName { get; set; } + public string AuthCookieSchemaName { get; set; } public AbpAntiForgeryOptions() { - TokenCookieName = "XSRF-TOKEN"; - AuthCookieName = ".AspNetCore.Identity.Application"; + TokenCookie = new CookieBuilder + { + Name = "XSRF-TOKEN", + HttpOnly = false, + IsEssential = true, + Expiration = TimeSpan.FromDays(3650) //10 years! + }; + + AuthCookieSchemaName = "Identity.Application"; } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs index a544de4f17a..22818991814 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs @@ -6,10 +6,11 @@ using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.Mvc.AntiForgery { - public class AbpValidateAntiforgeryTokenAuthorizationFilter : IAsyncAuthorizationFilter, IAntiforgeryPolicy + public class AbpValidateAntiforgeryTokenAuthorizationFilter : IAsyncAuthorizationFilter, IAntiforgeryPolicy, ITransientDependency { private IAntiforgery _antiforgery; private readonly AntiforgeryOptions _antiforgeryOptions; diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AspNetCoreAbpAntiForgeryManager.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AspNetCoreAbpAntiForgeryManager.cs index f016c366718..ff1ec26d1c2 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AspNetCoreAbpAntiForgeryManager.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AspNetCoreAbpAntiForgeryManager.cs @@ -26,7 +26,11 @@ public AspNetCoreAbpAntiForgeryManager( public void SetCookie() { - HttpContext.Response.Cookies.Append(Options.TokenCookieName, GenerateToken()); + HttpContext.Response.Cookies.Append( + Options.TokenCookie.Name, + GenerateToken(), + Options.TokenCookie.Build(HttpContext) + ); } public string GenerateToken() @@ -34,4 +38,4 @@ public string GenerateToken() return _antiforgery.GetAndStoreTokens(_httpContextAccessor.HttpContext).RequestToken; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationController.cs index 67c373585e6..89282110b99 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationController.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationController.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.AntiForgery; namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations { @@ -9,17 +10,21 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations public class AbpApplicationConfigurationController : AbpController, IAbpApplicationConfigurationAppService { private readonly IAbpApplicationConfigurationAppService _applicationConfigurationAppService; + private readonly IAbpAntiForgeryManager _antiForgeryManager; public AbpApplicationConfigurationController( - IAbpApplicationConfigurationAppService applicationConfigurationAppService) + IAbpApplicationConfigurationAppService applicationConfigurationAppService, + IAbpAntiForgeryManager antiForgeryManager) { _applicationConfigurationAppService = applicationConfigurationAppService; + _antiForgeryManager = antiForgeryManager; } [HttpGet] public async Task GetAsync() { + _antiForgeryManager.SetCookie(); return await _applicationConfigurationAppService.GetAsync(); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationScriptController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationScriptController.cs index d4ce99dc12e..7a773d92ebd 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationScriptController.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationScriptController.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Mvc.AntiForgery; using Volo.Abp.Auditing; using Volo.Abp.Http; using Volo.Abp.Json; @@ -20,17 +21,20 @@ public class AbpApplicationConfigurationScriptController : AbpController private readonly IJsonSerializer _jsonSerializer; private readonly AbpAspNetCoreMvcOptions _options; private readonly IJavascriptMinifier _javascriptMinifier; + private readonly IAbpAntiForgeryManager _antiForgeryManager; public AbpApplicationConfigurationScriptController( IAbpApplicationConfigurationAppService configurationAppService, IJsonSerializer jsonSerializer, IOptions options, - IJavascriptMinifier javascriptMinifier) + IJavascriptMinifier javascriptMinifier, + IAbpAntiForgeryManager antiForgeryManager) { _configurationAppService = configurationAppService; _jsonSerializer = jsonSerializer; _options = options.Value; _javascriptMinifier = javascriptMinifier; + _antiForgeryManager = antiForgeryManager; } [HttpGet] @@ -39,6 +43,8 @@ public async Task Get() { var script = CreateAbpExtendScript(await _configurationAppService.GetAsync()); + _antiForgeryManager.SetCookie(); + return Content( _options.MinifyGeneratedScript == true ? _javascriptMinifier.Minify(script) From e58842c8d6f4eaf7a8b613d0ebe238f2513b1fc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Oct 2020 14:38:02 +0300 Subject: [PATCH 5/8] Check ABP's antiforgery cookie to determine the validation logic. --- ...cs => AbpAntiForgeryCookieNameProvider.cs} | 11 +++++++--- ...dateAntiforgeryTokenAuthorizationFilter.cs | 20 +++++++++---------- ...dateAntiforgeryTokenAuthorizationFilter.cs | 17 ++++++++-------- 3 files changed, 25 insertions(+), 23 deletions(-) rename framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/{AbpAntiForgeryAuthCookieNameProvider.cs => AbpAntiForgeryCookieNameProvider.cs} (70%) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryAuthCookieNameProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryCookieNameProvider.cs similarity index 70% rename from framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryAuthCookieNameProvider.cs rename to framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryCookieNameProvider.cs index 6cd18c82a47..fa51d168d6f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryAuthCookieNameProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryCookieNameProvider.cs @@ -4,12 +4,12 @@ namespace Volo.Abp.AspNetCore.Mvc.AntiForgery { - public class AbpAntiForgeryAuthCookieNameProvider : ITransientDependency + public class AbpAntiForgeryCookieNameProvider : ITransientDependency { private readonly IOptionsSnapshot _namedOptionsAccessor; private readonly AbpAntiForgeryOptions _abpAntiForgeryOptions; - public AbpAntiForgeryAuthCookieNameProvider( + public AbpAntiForgeryCookieNameProvider( IOptionsSnapshot namedOptionsAccessor, IOptions abpAntiForgeryOptions) { @@ -17,9 +17,14 @@ public AbpAntiForgeryAuthCookieNameProvider( _abpAntiForgeryOptions = abpAntiForgeryOptions.Value; } - public virtual string GetNameOrNull() + public virtual string GetAuthCookieNameOrNull() { return _namedOptionsAccessor.Get(_abpAntiForgeryOptions.AuthCookieSchemaName)?.Cookie?.Name; } + + public virtual string GetAntiForgeryCookieNameOrNull() + { + return _abpAntiForgeryOptions.TokenCookie.Name; + } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs index c0dbcd246a4..8858058375a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs @@ -2,29 +2,24 @@ using Microsoft.AspNetCore.Antiforgery; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.Mvc.AntiForgery { public class AbpAutoValidateAntiforgeryTokenAuthorizationFilter : AbpValidateAntiforgeryTokenAuthorizationFilter, ITransientDependency { - private readonly AntiforgeryOptions _antiforgeryOptions; - private readonly AbpAntiForgeryAuthCookieNameProvider _antiForgeryAuthCookieNameProvider; + private readonly AbpAntiForgeryCookieNameProvider _antiForgeryCookieNameProvider; public AbpAutoValidateAntiforgeryTokenAuthorizationFilter( IAntiforgery antiforgery, - IOptions antiforgeryOptions, - AbpAntiForgeryAuthCookieNameProvider antiForgeryAuthCookieNameProvider, + AbpAntiForgeryCookieNameProvider antiForgeryCookieNameProvider, ILogger logger) : base( antiforgery, - antiforgeryOptions, - antiForgeryAuthCookieNameProvider, + antiForgeryCookieNameProvider, logger) { - _antiForgeryAuthCookieNameProvider = antiForgeryAuthCookieNameProvider; - _antiforgeryOptions = antiforgeryOptions.Value; + _antiForgeryCookieNameProvider = antiForgeryCookieNameProvider; } protected override bool ShouldValidate(AuthorizationFilterContext context) @@ -34,7 +29,7 @@ protected override bool ShouldValidate(AuthorizationFilterContext context) return false; } - var authCookieName = _antiForgeryAuthCookieNameProvider.GetNameOrNull(); + var authCookieName = _antiForgeryCookieNameProvider.GetAuthCookieNameOrNull(); //Always perform antiforgery validation when request contains authentication cookie if (authCookieName != null && @@ -43,10 +38,13 @@ protected override bool ShouldValidate(AuthorizationFilterContext context) return true; } + var antiForgeryCookieName = _antiForgeryCookieNameProvider.GetAntiForgeryCookieNameOrNull(); + //No need to validate if antiforgery cookie is not sent. //That means the request is sent from a non-browser client. //See https://github.com/aspnet/Antiforgery/issues/115 - if (!context.HttpContext.Request.Cookies.ContainsKey(_antiforgeryOptions.Cookie.Name)) + if (antiForgeryCookieName != null && + !context.HttpContext.Request.Cookies.ContainsKey(antiForgeryCookieName)) { return false; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs index 22818991814..abb7107bf92 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs @@ -5,7 +5,6 @@ using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.Mvc.AntiForgery @@ -13,20 +12,17 @@ namespace Volo.Abp.AspNetCore.Mvc.AntiForgery public class AbpValidateAntiforgeryTokenAuthorizationFilter : IAsyncAuthorizationFilter, IAntiforgeryPolicy, ITransientDependency { private IAntiforgery _antiforgery; - private readonly AntiforgeryOptions _antiforgeryOptions; - private readonly AbpAntiForgeryAuthCookieNameProvider _antiForgeryAuthCookieNameProvider; + private readonly AbpAntiForgeryCookieNameProvider _antiForgeryCookieNameProvider; private readonly ILogger _logger; public AbpValidateAntiforgeryTokenAuthorizationFilter( IAntiforgery antiforgery, - IOptions antiforgeryOptions, - AbpAntiForgeryAuthCookieNameProvider antiForgeryAuthCookieNameProvider, + AbpAntiForgeryCookieNameProvider antiForgeryCookieNameProvider, ILogger logger) { _antiforgery = antiforgery; - _antiforgeryOptions = antiforgeryOptions.Value; _logger = logger; - _antiForgeryAuthCookieNameProvider = antiForgeryAuthCookieNameProvider; + _antiForgeryCookieNameProvider = antiForgeryCookieNameProvider; } public async Task OnAuthorizationAsync(AuthorizationFilterContext context) @@ -63,7 +59,7 @@ protected virtual bool ShouldValidate(AuthorizationFilterContext context) return false; } - var authCookieName = _antiForgeryAuthCookieNameProvider.GetNameOrNull(); + var authCookieName = _antiForgeryCookieNameProvider.GetAuthCookieNameOrNull(); //Always perform antiforgery validation when request contains authentication cookie if (authCookieName != null && @@ -72,10 +68,13 @@ protected virtual bool ShouldValidate(AuthorizationFilterContext context) return true; } + var antiForgeryCookieName = _antiForgeryCookieNameProvider.GetAntiForgeryCookieNameOrNull(); + //No need to validate if antiforgery cookie is not sent. //That means the request is sent from a non-browser client. //See https://github.com/aspnet/Antiforgery/issues/115 - if (!context.HttpContext.Request.Cookies.ContainsKey(_antiforgeryOptions.Cookie.Name)) + if (antiForgeryCookieName != null && + !context.HttpContext.Request.Cookies.ContainsKey(antiForgeryCookieName)) { return false; } From 0cf934889855c87a5dfb5936118f54afdbbd14da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Oct 2020 14:45:55 +0300 Subject: [PATCH 6/8] Refactor AbpAutoValidateAntiforgeryTokenAuthorizationFilter: Reduce duplication. --- ...dateAntiforgeryTokenAuthorizationFilter.cs | 50 +++---------------- ...dateAntiforgeryTokenAuthorizationFilter.cs | 15 ------ 2 files changed, 8 insertions(+), 57 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs index 8858058375a..04142d680e9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs @@ -8,8 +8,6 @@ namespace Volo.Abp.AspNetCore.Mvc.AntiForgery { public class AbpAutoValidateAntiforgeryTokenAuthorizationFilter : AbpValidateAntiforgeryTokenAuthorizationFilter, ITransientDependency { - private readonly AbpAntiForgeryCookieNameProvider _antiForgeryCookieNameProvider; - public AbpAutoValidateAntiforgeryTokenAuthorizationFilter( IAntiforgery antiforgery, AbpAntiForgeryCookieNameProvider antiForgeryCookieNameProvider, @@ -19,58 +17,26 @@ public AbpAutoValidateAntiforgeryTokenAuthorizationFilter( antiForgeryCookieNameProvider, logger) { - _antiForgeryCookieNameProvider = antiForgeryCookieNameProvider; + } protected override bool ShouldValidate(AuthorizationFilterContext context) { - if (!ShouldValidateInternal(context)) - { - return false; - } - - var authCookieName = _antiForgeryCookieNameProvider.GetAuthCookieNameOrNull(); - - //Always perform antiforgery validation when request contains authentication cookie - if (authCookieName != null && - context.HttpContext.Request.Cookies.ContainsKey(authCookieName)) - { - return true; - } - - var antiForgeryCookieName = _antiForgeryCookieNameProvider.GetAntiForgeryCookieNameOrNull(); - - //No need to validate if antiforgery cookie is not sent. - //That means the request is sent from a non-browser client. - //See https://github.com/aspnet/Antiforgery/issues/115 - if (antiForgeryCookieName != null && - !context.HttpContext.Request.Cookies.ContainsKey(antiForgeryCookieName)) + if (IsIgnoredHttpMethod(context)) { return false; } - // Anything else requires a token. - return true; + return base.ShouldValidate(context); } - private static bool ShouldValidateInternal(AuthorizationFilterContext context) + protected virtual bool IsIgnoredHttpMethod(AuthorizationFilterContext context) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - var method = context.HttpContext.Request.Method; - if (string.Equals("GET", method, StringComparison.OrdinalIgnoreCase) || - string.Equals("HEAD", method, StringComparison.OrdinalIgnoreCase) || - string.Equals("TRACE", method, StringComparison.OrdinalIgnoreCase) || - string.Equals("OPTIONS", method, StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - // Anything else requires a token. - return true; + return string.Equals("GET", method, StringComparison.OrdinalIgnoreCase) || + string.Equals("HEAD", method, StringComparison.OrdinalIgnoreCase) || + string.Equals("TRACE", method, StringComparison.OrdinalIgnoreCase) || + string.Equals("OPTIONS", method, StringComparison.OrdinalIgnoreCase); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs index abb7107bf92..fd0c5e6a019 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs @@ -54,11 +54,6 @@ public async Task OnAuthorizationAsync(AuthorizationFilterContext context) protected virtual bool ShouldValidate(AuthorizationFilterContext context) { - if (!ShouldValidateInternal(context)) - { - return false; - } - var authCookieName = _antiForgeryCookieNameProvider.GetAuthCookieNameOrNull(); //Always perform antiforgery validation when request contains authentication cookie @@ -82,15 +77,5 @@ protected virtual bool ShouldValidate(AuthorizationFilterContext context) // Anything else requires a token. return true; } - - private static bool ShouldValidateInternal(AuthorizationFilterContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - return true; - } } } From 9e7a64415795751722caec6ecde7894b118c3f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Oct 2020 14:51:40 +0300 Subject: [PATCH 7/8] Remove AbpAntiForgeryPreOptions --- .../Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs | 7 +------ .../Mvc/AntiForgery/AbpAntiForgeryOptions.cs | 6 ++++++ .../Mvc/AntiForgery/AbpAntiForgeryPreOptions.cs | 10 ---------- ...AutoValidateAntiforgeryTokenAuthorizationFilter.cs | 11 ++++++++++- 4 files changed, 17 insertions(+), 17 deletions(-) delete mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryPreOptions.cs 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 f1efac83ceb..3097a3c7251 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 @@ -95,14 +95,9 @@ public override void ConfigureServices(ServiceConfigurationContext context) } }); - var antiForgeryPreOptions = context.Services.ExecutePreConfiguredActions(); - var mvcCoreBuilder = context.Services.AddMvcCore(options => { - if (antiForgeryPreOptions.AutoValidate) - { - options.Filters.Add(new AbpAutoValidateAntiforgeryTokenAttribute()); - } + options.Filters.Add(new AbpAutoValidateAntiforgeryTokenAttribute()); }); context.Services.ExecutePreConfiguredActions(mvcCoreBuilder); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs index 1e21482981d..f46763ab0c4 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Microsoft.AspNetCore.Http; namespace Volo.Abp.AspNetCore.Mvc.AntiForgery @@ -17,6 +18,11 @@ public class AbpAntiForgeryOptions /// public string AuthCookieSchemaName { get; set; } + /// + /// Default value: true. + /// + public bool AutoValidate { get; set; } = true; + public AbpAntiForgeryOptions() { TokenCookie = new CookieBuilder diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryPreOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryPreOptions.cs deleted file mode 100644 index 887153fd1b7..00000000000 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryPreOptions.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Volo.Abp.AspNetCore.Mvc.AntiForgery -{ - public class AbpAntiForgeryPreOptions - { - /// - /// Default value: true. - /// - public bool AutoValidate { get; set; } = true; - } -} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs index 04142d680e9..40ed6fc509b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs @@ -2,26 +2,35 @@ using Microsoft.AspNetCore.Antiforgery; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.Mvc.AntiForgery { public class AbpAutoValidateAntiforgeryTokenAuthorizationFilter : AbpValidateAntiforgeryTokenAuthorizationFilter, ITransientDependency { + private readonly AbpAntiForgeryOptions _options; + public AbpAutoValidateAntiforgeryTokenAuthorizationFilter( IAntiforgery antiforgery, AbpAntiForgeryCookieNameProvider antiForgeryCookieNameProvider, + IOptions options, ILogger logger) : base( antiforgery, antiForgeryCookieNameProvider, logger) { - + _options = options.Value; } protected override bool ShouldValidate(AuthorizationFilterContext context) { + if (!_options.AutoValidate) + { + return false; + } + if (IsIgnoredHttpMethod(context)) { return false; From 71c97a0d8962175090e4a18633cff362fdfa2791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 7 Oct 2020 15:27:46 +0300 Subject: [PATCH 8/8] Added antiforgery options --- .../AbpAntiForgeryCookieNameProvider.cs | 5 ++++ .../Mvc/AntiForgery/AbpAntiForgeryOptions.cs | 29 +++++++++++++++++++ ...dateAntiforgeryTokenAuthorizationFilter.cs | 24 +++++++++++---- .../System/AbpObjectExtensions.cs | 14 ++++++++- 4 files changed, 66 insertions(+), 6 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryCookieNameProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryCookieNameProvider.cs index fa51d168d6f..66cd8701def 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryCookieNameProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryCookieNameProvider.cs @@ -19,6 +19,11 @@ public AbpAntiForgeryCookieNameProvider( public virtual string GetAuthCookieNameOrNull() { + if (_abpAntiForgeryOptions.AuthCookieSchemaName == null) + { + return null; + } + return _namedOptionsAccessor.Get(_abpAntiForgeryOptions.AuthCookieSchemaName)?.Cookie?.Name; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs index f46763ab0c4..44c35e9e0a4 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using JetBrains.Annotations; using Microsoft.AspNetCore.Http; namespace Volo.Abp.AspNetCore.Mvc.AntiForgery @@ -23,8 +24,34 @@ public class AbpAntiForgeryOptions /// public bool AutoValidate { get; set; } = true; + /// + /// A predicate to filter types to auto-validate. + /// Return true to select the type to validate. + /// Default: returns true for all given types. + /// + [NotNull] + public Predicate AutoValidateFilter + { + get => _autoValidateFilter; + set => _autoValidateFilter = Check.NotNull(value, nameof(value)); + } + private Predicate _autoValidateFilter; + + /// + /// Default methods: "GET", "HEAD", "TRACE", "OPTIONS". + /// + [NotNull] + public HashSet AutoValidateIgnoredHttpMethods + { + get => _autoValidateIgnoredHttpMethods; + set => _autoValidateIgnoredHttpMethods = Check.NotNull(value, nameof(value)); + } + private HashSet _autoValidateIgnoredHttpMethods; + public AbpAntiForgeryOptions() { + AutoValidateFilter = type => true; + TokenCookie = new CookieBuilder { Name = "XSRF-TOKEN", @@ -34,6 +61,8 @@ public AbpAntiForgeryOptions() }; AuthCookieSchemaName = "Identity.Application"; + + AutoValidateIgnoredHttpMethods = new HashSet {"GET", "HEAD", "TRACE", "OPTIONS"}; } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs index 40ed6fc509b..8affb3aa088 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs @@ -1,5 +1,6 @@ using System; using Microsoft.AspNetCore.Antiforgery; +using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -31,6 +32,19 @@ protected override bool ShouldValidate(AuthorizationFilterContext context) return false; } + if(context.ActionDescriptor.IsControllerAction()) + { + var controllerType = context.ActionDescriptor + .AsControllerActionDescriptor() + .ControllerTypeInfo + .AsType(); + + if (!_options.AutoValidateFilter(controllerType)) + { + return false; + } + } + if (IsIgnoredHttpMethod(context)) { return false; @@ -41,11 +55,11 @@ protected override bool ShouldValidate(AuthorizationFilterContext context) protected virtual bool IsIgnoredHttpMethod(AuthorizationFilterContext context) { - var method = context.HttpContext.Request.Method; - return string.Equals("GET", method, StringComparison.OrdinalIgnoreCase) || - string.Equals("HEAD", method, StringComparison.OrdinalIgnoreCase) || - string.Equals("TRACE", method, StringComparison.OrdinalIgnoreCase) || - string.Equals("OPTIONS", method, StringComparison.OrdinalIgnoreCase); + return context.HttpContext + .Request + .Method + .ToUpperInvariant() + .IsIn(_options.AutoValidateIgnoredHttpMethods); } } } diff --git a/framework/src/Volo.Abp.Core/System/AbpObjectExtensions.cs b/framework/src/Volo.Abp.Core/System/AbpObjectExtensions.cs index d1067a383ff..958398e0c55 100644 --- a/framework/src/Volo.Abp.Core/System/AbpObjectExtensions.cs +++ b/framework/src/Volo.Abp.Core/System/AbpObjectExtensions.cs @@ -1,4 +1,5 @@ -using System.ComponentModel; +using System.Collections.Generic; +using System.ComponentModel; using System.Globalization; using System.Linq; @@ -49,6 +50,17 @@ public static bool IsIn(this T item, params T[] list) return list.Contains(item); } + /// + /// Check if an item is in the given enumerable. + /// + /// Item to check + /// Items + /// Type of the items + public static bool IsIn(this T item, IEnumerable items) + { + return items.Contains(item); + } + /// /// Can be used to conditionally perform a function /// on an object and return the modified or the original object.