我想自定义 CSRF 令牌验证失败时客户端收到的响应。我正在查看 ASP.NET 的源代码,发现一个我认为可以处理这个问题的中间件。
通过查看它,我发现它在验证失败时设置了一个带有错误的IAntiForgeryValidationFeature
,因此我创建了一个中间件来检查这一点。
public class CustomAntiForgeryValidationResponseMiddleware(RequestDelegate next)
{
public async Task InvokeAsync(HttpContext context)
{
IAntiforgeryValidationFeature? antiforgeryValidation = context.Features.Get<IAntiforgeryValidationFeature>();
if (antiforgeryValidation is not null && !antiforgeryValidation.IsValid)
{
context.Response.StatusCode = 403;
await context.Response.WriteAsJsonAsync(new ProblemDetails()
{
Title = "Forbidden",
Detail = "User is not allowed to perform this action",
Status = 403,
Extensions = new Dictionary<string, object?>()
{
{ "errors", new ApiError[] { new("Invalid or missing CSRF token") } }
}
});
}
await next(context);
}
}
然后,我在请求管道中的身份验证中间件之前添加了中间件。
app.UseMiddleware<CustomAntiForgeryValidationResponseMiddleware>();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
但是,即使在需要 CSRF 令牌的端点上,该功能也始终为空。我做错了什么?
因此,在捕获防伪令牌验证异常之前,我们需要了解
防伪令牌工作流程:
为了帮助防止 CSRF 攻击,ASP.NET MVC 使用防伪造令牌,也称为请求验证令牌。
方法捕获400错误并检查请求头或表单是否包含Anti-Forgery token:如果请求头或表单不包含Anti-Forgery token ,这是一个Anti-Forgery token异常,代码如下:
app.UseStatusCodePages(async context =>
{
var response = context.HttpContext.Response;
if (response.StatusCode == 400 )
{
//check Anti-Forgery Tokens workflow: https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/preventing-cross-site-request-forgery-csrf-attacks#anti-forgery-tokens
if (!context.HttpContext.Request.Headers.ContainsKey("RequestVerificationToken") & !context.HttpContext.Request.Form.ContainsKey("__RequestVerificationToken"))
{
//Anti-Forgery Tokens exceptions
response.StatusCode = StatusCodes.Status403Forbidden;
await response.WriteAsync("Antiforgery token validation failed.");
}
else
{
//other model validation error
await response.WriteAsync("Other 400 error.");
}
}
});
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();