Browse Source

Enable AbpAutoValidateAntiforgeryTokenAttribute by default.

pull/5728/head
Halil İbrahim Kalkan 6 years ago
parent
commit
f8c9d7ddb9
  1. 11
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
  2. 10
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs
  3. 10
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryPreOptions.cs
  4. 37
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAttribute.cs
  5. 78
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAutoValidateAntiforgeryTokenAuthorizationFilter.cs
  6. 37
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiForgeryTokenAttribute.cs
  7. 100
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpValidateAntiforgeryTokenAuthorizationFilter.cs
  8. 1
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs

11
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs

@ -22,6 +22,7 @@ using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Volo.Abp.ApiVersioning; using Volo.Abp.ApiVersioning;
using Volo.Abp.AspNetCore.Mvc.AntiForgery;
using Volo.Abp.AspNetCore.Mvc.ApiExploring; using Volo.Abp.AspNetCore.Mvc.ApiExploring;
using Volo.Abp.AspNetCore.Mvc.Conventions; using Volo.Abp.AspNetCore.Mvc.Conventions;
using Volo.Abp.AspNetCore.Mvc.DataAnnotations; using Volo.Abp.AspNetCore.Mvc.DataAnnotations;
@ -94,7 +95,15 @@ namespace Volo.Abp.AspNetCore.Mvc
} }
}); });
var mvcCoreBuilder = context.Services.AddMvcCore(); var antiForgeryPreOptions = context.Services.ExecutePreConfiguredActions<AbpAntiForgeryPreOptions>();
var mvcCoreBuilder = context.Services.AddMvcCore(options =>
{
if (antiForgeryPreOptions.AutoValidate)
{
options.Filters.Add(new AbpAutoValidateAntiforgeryTokenAttribute());
}
});
context.Services.ExecutePreConfiguredActions(mvcCoreBuilder); context.Services.ExecutePreConfiguredActions(mvcCoreBuilder);
var abpMvcDataAnnotationsLocalizationOptions = context.Services var abpMvcDataAnnotationsLocalizationOptions = context.Services

10
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AntiForgery/AbpAntiForgeryOptions.cs

@ -9,15 +9,15 @@
public string TokenCookieName { get; set; } public string TokenCookieName { get; set; }
/// <summary> /// <summary>
/// Get/sets header name to transfer Anti Forgery token from client to the server. /// Used to find auth cookie when validating Anti Forgery token.
/// Default value: "X-XSRF-TOKEN". /// Default value: ".AspNet.ApplicationCookie".
/// </summary> /// </summary>
public string TokenHeaderName { get; set; } public string AuthorizationCookieName { get; set; }
public AbpAntiForgeryOptions() public AbpAntiForgeryOptions()
{ {
TokenCookieName = "XSRF-TOKEN"; TokenCookieName = "XSRF-TOKEN";
TokenHeaderName = "X-XSRF-TOKEN"; AuthorizationCookieName = ".AspNet.ApplicationCookie";
} }
} }
} }

10
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
{
/// <summary>
/// Default value: true.
/// </summary>
public bool AutoValidate { get; set; } = true;
}
}

37
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
{
/// <summary>
/// Gets the order value for determining the order of execution of filters. Filters execute in
/// ascending numeric value of the <see cref="Order"/> property.
/// </summary>
/// <remarks>
/// <para>
/// Filters are executed in a sequence determined by an ascending sort of the <see cref="Order"/> property.
/// </para>
/// <para>
/// 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).
/// </para>
/// <para>
/// Look at <see cref="IOrderedFilter.Order"/> for more detailed info.
/// </para>
/// </remarks>
public int Order { get; set; } = 1000;
/// <inheritdoc />
public bool IsReusable => true;
/// <inheritdoc />
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
return serviceProvider.GetRequiredService<AbpAutoValidateAntiforgeryTokenAuthorizationFilter>();
}
}
}

78
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<CookieAuthenticationOptions> _namedOptionsAccessor;
private readonly AbpAntiForgeryOptions _abpAntiForgeryOptions;
public AbpAutoValidateAntiforgeryTokenAuthorizationFilter(
IAntiforgery antiforgery,
IOptions<AntiforgeryOptions> antiforgeryOptions,
IOptions<AbpAntiForgeryOptions> abpAntiForgeryOptions,
IOptionsSnapshot<CookieAuthenticationOptions> 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;
}
}
}

37
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
{
/// <summary>
/// Gets the order value for determining the order of execution of filters. Filters execute in
/// ascending numeric value of the <see cref="Order"/> property.
/// </summary>
/// <remarks>
/// <para>
/// Filters are executed in an ordering determined by an ascending sort of the <see cref="Order"/> property.
/// </para>
/// <para>
/// 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).
/// </para>
/// <para>
/// Look at <see cref="IOrderedFilter.Order"/> for more detailed info.
/// </para>
/// </remarks>
public int Order { get; set; } = 1000;
/// <inheritdoc />
public bool IsReusable => true;
/// <inheritdoc />
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
return serviceProvider.GetRequiredService<AbpValidateAntiforgeryTokenAuthorizationFilter>();
}
}
}

100
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<CookieAuthenticationOptions> _namedOptionsAccessor;
private readonly AbpAntiForgeryOptions _abpAntiForgeryOptions;
private readonly ILogger _logger;
public AbpValidateAntiforgeryTokenAuthorizationFilter(
IAntiforgery antiforgery,
IOptions<AntiforgeryOptions> antiforgeryOptions,
IOptions<AbpAntiForgeryOptions> abpAntiForgeryOptions,
IOptionsSnapshot<CookieAuthenticationOptions> 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<IAntiforgeryPolicy>(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;
}
}
}

1
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs

@ -5,7 +5,6 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Nito.AsyncEx; using Nito.AsyncEx;

Loading…
Cancel
Save