如果您可以在编译时确定应该忽略 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 令牌。