我一直在尝试重新创建一个Ajax版本的ValidateAntiForgeryToken - 有很多关于如何为MVC的先前版本做到这一点的博客文章,但与最新的MVC 6,没有任何代码是相关的。然而,我所追求的核心原则是验证看看Cookie和页眉的__RequestVerificationToken
,而不是将Cookie与表单值进行比较。我使用的是MVC 6.0.0-rc1-final,dnx451框架,所有的Microsoft.Extensions库都是1.0.0-rc1-final。ValidateAntiForgeryToken Ajax请求与AspNet核心MVC
我最初的想法是继承ValidateAntiForgeryTokenAttribute,但在查看源代码时,我需要返回自己的授权过滤器实现以使其能够查看标题。
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public class ValidateAjaxAntiForgeryTokenAttribute : Attribute, IFilterFactory, IFilterMetadata, IOrderedFilter { public int Order { get; set; } public bool IsReusable => true; public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) { return serviceProvider.GetRequiredService<ValidateAjaxAntiforgeryTokenAuthorizationFilter>(); } }
这样,然后我做了我自己的ValidateAntiforgeryTokenAuthorizationFilter
public class ValidateAjaxAntiforgeryTokenAuthorizationFilter : IAsyncAuthorizationFilter, IAntiforgeryPolicy { private readonly IAntiforgery _antiforgery; private readonly ILogger _logger; public ValidateAjaxAntiforgeryTokenAuthorizationFilter(IAntiforgery antiforgery, ILoggerFactory loggerFactory) { if (antiforgery == null) { throw new ArgumentNullException(nameof(antiforgery)); } _antiforgery = antiforgery; _logger = loggerFactory.CreateLogger<ValidateAjaxAntiforgeryTokenAuthorizationFilter>(); } public async Task OnAuthorizationAsync(AuthorizationContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (IsClosestAntiforgeryPolicy(context.Filters) && ShouldValidate(context)) { try { await _antiforgery.ValidateRequestAsync(context.HttpContext); } catch (AjaxAntiforgeryValidationException exception) { _logger.LogInformation(1, string.Concat("Ajax Antiforgery token validation failed. ", exception.Message)); context.Result = new BadRequestResult(); } } } protected virtual bool ShouldValidate(AuthorizationContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } return true; } private bool IsClosestAntiforgeryPolicy(IList<IFilterMetadata> filters) { // Determine if this instance is the 'effective' antiforgery policy. for (var i = filters.Count - 1; i >= 0; i--) { var filter = filters[i]; if (filter is IAntiforgeryPolicy) { return object.ReferenceEquals(this, filter); } } Debug.Fail("The current instance should be in the list of filters."); return false; } }
但版本,我找不到合适的NuGet包和命名空间包含IAntiforgeryPolicy。当我在GitHub上找到接口时 - 我能找到哪个包?
我的下一次尝试是改为在IAntiforgery注射后,并用我自己的AjaxAntiforgery
替换DefaultAntiforgery。
public class AjaxAntiforgery : DefaultAntiforgery { private readonly AntiforgeryOptions _options; private readonly IAntiforgeryTokenGenerator _tokenGenerator; private readonly IAntiforgeryTokenSerializer _tokenSerializer; private readonly IAntiforgeryTokenStore _tokenStore; private readonly ILogger<AjaxAntiforgery> _logger; public AjaxAntiforgery( IOptions<AntiforgeryOptions> antiforgeryOptionsAccessor, IAntiforgeryTokenGenerator tokenGenerator, IAntiforgeryTokenSerializer tokenSerializer, IAntiforgeryTokenStore tokenStore, ILoggerFactory loggerFactory) { _options = antiforgeryOptionsAccessor.Value; _tokenGenerator = tokenGenerator; _tokenSerializer = tokenSerializer; _tokenStore = tokenStore; _logger = loggerFactory.CreateLogger<AjaxAntiforgery>(); } }
我走到这一步之前,我陷入停滞,因为没有对ILoggerFactory
的CreateLogger<T>()
没有通用的方法。 DefaultAntiforgery
的源代码有Microsoft.Extensions.Options
,但我无法在任何Nuget包中找到该名称空间。 Microsoft.Extensions.OptionsModel
存在,但只是带来了IOptions<out TOptions>
界面。为了全面了解这一点,一旦我得到了授权过滤器的工作,或者我得到了一个新的实现IAntiforgery
,我在哪里或如何注册依赖注入来使用它 - 并且仅限于操作我会接受Ajax请求?
你有代码示例吗? – Grandizer