【问题标题】:How to implement custom ValidateAntiforgeryTokenAuthorizationFilter in ASP.NET Core 3.1如何在 ASP.NET Core 3.1 中实现自定义 ValidateAntiforgeryTokenAuthorizationFilter
【发布时间】:2020-01-01 13:41:56
【问题描述】:

我想实现一个过滤器,在使用身份验证令牌身份验证 (Bearer) 时跳过对防伪令牌的验证。

在 ASP.NET Core 2.2 中,ValidateAntiforgeryTokenAuthorizationFilterAutoValidateAntiforgeryTokenAuthorizationFilter 是公共的(即使位于 Microsoft.AspNetCore.Mvc.ViewFeatures.Internal 命名空间中),所以我能够从后者继承并轻松覆盖 ShouldValidate 方法.

在 ASP.NET Core 3.0 中,它们变成了内部的,因此不能仅从它们继承。我可以复制粘贴代码,但这显然不是理想的解决方案。

我正在关注 MSDN 的 Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core 文章,但它并没有真正提及与我的场景相关的任何内容。

【问题讨论】:

    标签: asp.net-core csrf asp.net-core-webapi antiforgerytoken


    【解决方案1】:

    如果您可以在编译时确定应该忽略 csrf 令牌,通常可以使用 [IgnoreAntiforgeryToken] 属性。如果您希望在运行时拥有这样的能力,您可以创建一个自定义 FilterProvider,如果有 Authroization: Bearer json-web-token 标头,它将 提供一个 IAntiforgeryPolicy

    例如,我们可以创建一个自定义的AutoSkipAntiforgeryFilterProvider,如下所示:

    public class AutoSkipAntiforgeryFilterProvider: IFilterProvider
    {
        private const string BEARER_STRING = "Bearer";
        public int Order => 999;
        public void OnProvidersExecuted(FilterProviderContext context) { }
        public void OnProvidersExecuting(FilterProviderContext context)
        {
            if (context == null) { throw new ArgumentNullException(nameof(context)); }
            if (context.ActionContext.ActionDescriptor.FilterDescriptors != null)
            {
                var headers = context.ActionContext.HttpContext.Request.Headers;
                if (headers.ContainsKey("Authorization"))
                {
                    var header = headers["Authorization"].FirstOrDefault();
                    if(header.StartsWith(BEARER_STRING,StringComparison.OrdinalIgnoreCase))
                    {
                        var FilterDescriptor = new FilterDescriptor(SkipAntiforgeryPolicy.Instance, FilterScope.Last);
                        var filterItem = new FilterItem( FilterDescriptor,SkipAntiforgeryPolicy.Instance);
                        context.Results.Add(filterItem);
                    }
                }
            }
        }
    
        // a dummy IAntiforgeryPolicy
        class SkipAntiforgeryPolicy : IAntiforgeryPolicy, IAsyncAuthorizationFilter
        {
            // a singleton 
            public static SkipAntiforgeryPolicy Instance = new SkipAntiforgeryPolicy();
            public Task OnAuthorizationAsync(AuthorizationFilterContext context) => Task.CompletedTask;
        }
    }
    

    并在 Startup 中注册此过滤器提供程序:

    services.TryAddEnumerable( ServiceDescriptor.Singleton<IFilterProvider, AutoSkipAntiforgeryFilterProvider>());
    

    现在它会绕过AntiForgery,即使有[ValidateAntiForgeryToken]属性。


    [演示]

    假设我们有一个用[ValidateAntiForgeryToken]注解的动作方法:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("Id,Name")] XModel xModel)
    {
        ....
    }
    

    通常,它会使用 CSRF 令牌保护此方法。但是,如果您发送如下请求:

    POST /XModels/创建 HTTP/1.1 授权:承载 Xyz 内容类型:application/x-www-form-urlencoded ...

    它不会验证 csrf 令牌。

    【讨论】:

    • 太好了,就像魅力一样,谢谢!对我来说并不完全明显的一件事是在哪里注册它 - 我最初将它添加到 services.AddMvc(config =&gt; { //here }) 块内,但它不起作用。我的最终设置如下:services.TryAddEnumerable(ServiceDescriptor.Singleton&lt;IFilterProvider, SkipAntiforgeryWhenAuthTokenUsedFilterProvider&gt;()); services.AddMvc(config =&gt; { config.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()); });
    • @GrzegorzSmulko 很高兴听到它对您有用。顺便说一句,我们更喜欢端点路由而不是UseMvc() :)
    • 谢谢!还有一件事,我试图按照您的建议摆脱AddMvc() - 这完全有道理,因为我不需要任何与视图/剃刀相关的功能。问题是,似乎没有其他方法可以将ValidateAntiforgeryTokenAuthorizationFilter 添加到服务中,而不是通过运行AddViews(或调用它的AddMvc),因为ValidateAntiforgeryTokenAuthorizationFilter 在最新版本的ASP 中是内部的.NET 核心。或者也许我做错了什么,我根本不应该打电话给config.Filters.Add(new AutoValidateAntiforgeryTokenAttribute())
    • @GrzegorzSmulko 1. 我不需要任何视图/剃须刀相关功能:据我所知,Antiforgery 是一个视图功能,如果您不想查看,您也不需要 Antiforgery :) 2. ValidateAntiforgeryTokenAuthorizationFilter 是内部的:是的,这是真的。但是如果添加AddControllersWithViews(),则不需要手动注册。它由 ASP.NET Core 自己注册。我们只需要注册AutoSkipAntiforgeryFilterProvider服务,因为它实现了IAntiforgeryPolicyValidateAntiforgeryTokenAuthorizationFilter会自动跳过Antiforgery令牌。
    • 是的。你是对的。简而言之,CSRF 的发生是因为浏览器自动发送带有凭据的伪造请求(来自其他站点)。当发送application/json的有效载荷时,我们不必关心CSRF(目前),因为application/json的请求不会被浏览器自动发送到服务器。这就是 ASP.NET Core 将 CSRF 视为 View Feature 的原因(这里的 View 是一个通用术语,包括 MVC/Razor Page/a Plain Html Page/SPA/...)。由于 ASP.NET Core 将此视为一个非常基本的视图功能,因此启用视图也会启用此 CSRF 验证过滤器。
    猜你喜欢
    • 2020-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多