.NET MVC,在 ValidateAntiForgeryToken 检查失败后做一些事情

.NET MVC, Do something after ValidateAntiForgeryToken check fails

在我的表格中我有

@Html.AntiForgeryToken()

并且接收控制器动作有

    [HttpPost, ValidateAntiForgeryToken]  
    public ActionResult Login(LoginViewModel model)  
    {
      //if detects a post request missing token, 
      //I wish to log form info for later inspection
    }

当 post 请求丢失令牌时,框架不会继续执行该方法。如果我想记录表单信息以供日后检查,我可以做什么以及在哪里?

 [HttpPost]
 public async Task<IActionResult> Method(int id)
 {
        var formParameters = await Context.Request.ReadFormAsync();
        var requestVerification = formParameters["RequestVerificationToken"];
        string cookieToken = null;
        string formToken = null;

        if (!string.IsNullOrWhiteSpace(requestVerification))
        {
        var tokens = requestVerification.Split(':');

        if (tokens != null && tokens.Length == 2)
        {
            cookieToken = tokens[0];
            formToken = tokens[1];
        }


        var antiForgery = Context.RequestServices.GetService<AntiForgery>();
        try
        {
            antiForgery.Validate(Context, new AntiForgeryTokenSet(formToken, cookieToken))}
        catch
        {
           //log
        }
  }

通过这种方式,您可以手动验证防伪标记,这样您就有机会让该方法执行。

另一种方法是创建一个自定义异常过滤器来捕获 AntiForgery 异常并从那里记录表单详细信息,详情如下:

public class AntiForgeryExceptionAttribute : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        // ANTIFORGERY TOKEN NOT PRESENT
        if (!filterContext.ExceptionHandled && filterContext.Exception is HttpAntiForgeryException)
        {
            var request = new HttpRequestWrapper(System.Web.HttpContext.Current.Request);
            // Use your own logging service to log the results
            var _logger = new LoggingService();
            foreach (var key in request.Form.AllKeys)
            {
                var value = request.Form[key];
                // "key" is the form input name and "value" is the form input value
                _logger.Log("~~> " + key + " ==> " + value);
            }

            filterContext.ExceptionHandled = true;
        }
    }
}

并在 global.asax 中注册自定义过滤器:

protected void Application_Start()
{
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    GlobalFilters.Filters.Add(new AntiForgeryExceptionAttribute());
}

这对原发布者来说可能不是特别有用,但如果您在 .Net Core 2.2 或更高的世界中,防伪令牌失败将不会引发异常,而是会生成 AntiforgeryValidationFailedResult。因此,您将希望针对该结果而不是异常创建过滤器。

有关详细信息和代码示例,请参阅