如何覆盖什么响应 [ValidateAntiForgeryToken] 返回或手动验证令牌?

问题描述

如果我为 API 方法使用 [ValidateAntiForgeryToken] 属性,我会得到自动生成的 HTTP400 JSON。我希望能够覆盖 JSON 内容。我可以以某种方式手动决定对验证问题的响应吗?

我实现了自己的:

public class ExceptionFilteraaAttribute : ActionFilterattribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        System.Console.WriteLine(context);
    }

    public override void OnActionExecuted(ActionExecutedContext context)
    {
        if (context?.Exception != null)
        {
            context.Result = new ObjectResult(...)
            {
                StatusCode = (int)HttpStatusCode.InternalServerError,};
            context.ExceptionHandled = true;
        }
    }
}

但它永远不会到达这个地方,因为已经 [ValidateAntiForgeryToken] 响应了请求。


我需要实施:

public class ChangedAntiforgeryResultFilter : ResultFilterattribute
{
    public override void OnResultExecuting(ResultExecutingContext context)
    {
  
//this is never hit
    if (context?.Result is AntiforgeryValidationFailedResult)
    {
        context.Result = new BadRequestObjectResult(new LoginErrorResponseDto
        {
            OperationId = context.HttpContext.Features?.Get<RequestTelemetry>()?.Context?.Operation?.Id
        });
    }
}

public override void OnResultExecuted(ResultExecutedContext context)
{
}

}

添加到我的控制器和我的方法属性

    [ValidateAntiForgeryToken]
    [ChangedAntiforgeryResultFilter]

我的 ChangedAntiForgeryResultFilter 永远不会到达,返回 400 并带有内容

解决方法

可以通过复制默认的 ValidateAntiforgeryTokenAuthorizationFilter 来构建您自己的授权过滤器,替换它生成的结果。一种更简单的方法(不需要您重新实现验证逻辑)是在默认的 [ValidateAntiForgeryToken] 之外添加一个结果过滤器,用于检查 AntiforgeryValidationFailedResult 并将其替换为其他内容。这样的过滤器看起来很简单:

public class ChangedAntiforgeryResultFilter : IAlwaysRunResultFilter
{
    public void OnResultExecuting(ResultExecutingContext context)
    {
        if (context.Result is AntiforgeryValidationFailedResult)
        {
            context.Result = new StatusCodeResult(500);
        }
    }

    public void OnResultExecuted(ResultExecutedContext context)
    { }
}
[HttpPost]
[ValidateAntiForgeryToken]
[TypeFilter(typeof(ChangedAntiforgeryResultFilter))]
public IActionResult ExampleAction(ExampleModle model)
    => View(model);

话虽如此,但我不建议更改响应代码。HTTP status codes 的定义非常精确。 4xx 错误表示存在 客户端 错误,而 5xx 错误表示存在 服务器 错误。客户端未发送正确的防伪令牌在很大程度上是客户端错误。在这种情况下返回 500 Internal Server Error 是错误的。

来自 AntiforgeryValidationFailedResult 的默认响应是 400 Bad Request,这是正确的结果:

400 (Bad Request) 状态码表示服务器由于被认为是客户端错误(例如,格式错误的请求语法、无效的请求消息帧或欺骗性的请求路由)而无法或不会处理请求.