我一直在嘗試重新創建一個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