MVC5 AntiForgeryToken - 如何处理"提供的防伪令牌是为用户",但当前用户是"xxx"." 例外?

use*_*366 15 exception-handling antiforgerytoken asp.net-mvc-5

我想通过AntiforgeryToken属性来保护我们的登录操作- 我知道为什么会出现该主题的异常,但我似乎找不到任何好的解决方案.

假设我们有以下情况:

  1. 现在是上午8点,应用程序用户开始工作,他们坐下来开始登录过程 - 现在很可能某些用户将获得相同的ValidationToken.在第一个登录后 - 所有其他人在尝试登录时将看到上述异常(或其他一些自定义异常屏幕).

  2. 有些用户登录,然后意外按下" 后退 "按钮并尝试再次登录 - 虽然这种情况不太可能发生,但是我不希望用户看到例外情况.

所以问题很简单 - 如何防止上述情况,或如何处理它们以便用户不会注意到任何事情.我尝试过以下方法:

  1. 设置AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; Global.asax的Application_Start中 - 它没有解决问题,我仍然得到相同的异常
  2. 使用[ValidateAntiForgeryToken]属性在方法上设置[OutputCache(NoStore = true,Duration = 0,VaryByParam ="None")] - 再次,那里没有运气

现在我正在考虑手动验证操作体中的令牌,捕获错误,并检查是否由匿名用户进行了尝试:

public ActionResult SomeAction()
{
    try
    {
        AntiForgery.Validate();
    }
    catch(HttpAntiForgeryException ex)
    {
        if(String.IsNullOrEmpty(HttpContext.User.Identity.Name))
        {
            throw;
        }
    }

    //Rest of action body here
    //..
    //..
}
Run Code Online (Sandbox Code Playgroud)

以上似乎可以防止错误 - 但它是否安全? 有什么替代品?

提前致谢.

最好的祝福.

编辑:

最终的"解决方案"是在登录表单上禁用令牌验证 - 可能有更好的方法来处理它,但似乎我找到的所有解决方案都是类似于我上面提到的丑陋的解决方法.

由于没有办法知道这些替代品是多么"安全"(如果它们是安全的),我们决定在登录时禁用令牌验证.

poo*_*pro 19

尝试设置(在global.cs中):

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
Run Code Online (Sandbox Code Playgroud)

这会将名称标识符添加到您的令牌中,

至于双重登录问题,请尝试使用脚本记录原始提交的日期和时间,以使用相同的令牌停止第二次提交.

// jQuery plugin to prevent double submission of forms
jQuery.fn.preventDoubleSubmission = function() {
  $(this).on('submit',function(e){
    var $form = $(this);

    if ($form.data('submitted') === true) {
      // Previously submitted - don't submit again
      e.preventDefault();
    } else {
      // Mark it so that the next submit can be ignored
      $form.data('submitted', true);
    }
  });

  // Keep chainability
  return this;
};
Run Code Online (Sandbox Code Playgroud)

所以我们知道一件事; 用户喜欢后退按钮并且有双击的习惯,这是AntiforgeryToken的一个大问题.

但是,根据您的应用程序的作用,有限制其强制的方法.最简单的方法是尽力让访问者不要觉得他们需要"回放"他们改变它的请求.

确保表单错误消息传递清晰简洁,以确保用户知道错误.上下文错误给予奖励积分.

始终在表单提交之间保持表单状态.除了密码或信用卡号码之外,没有理由感谢MVC表单助手.@Html.LabelFor(x => x.FirstName)

如果表单分布在选项卡或隐藏的div上,例如在Angular或ember.js等SPA框架中使用的那些,请智能显示控制器布局或表单,在显示错误时,表单提交中的错误实际来自.不要只是将它们指向家庭控制器或第一个标签.

"发生了什么事?" - 让用户知情

当AntiForgeryToken未验证您的网站时,将抛出System.Web.Mvc.HttpAntiForgeryException类型的异常.

如果你已经设置正确,你就会打开友好的错误,这意味着你的错误页面不会显示异常并显示一个很好的错误页面,告诉他们是什么.

通过捕获HttpAntiForgeryException,至少为用户提供针对这些异常的信息更丰富的页面,可以使这更容易一些.

private void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();

    if (ex is HttpAntiForgeryException)
    {
        Response.Clear();
        Server.ClearError(); //make sure you log the exception first
        Response.Redirect("/error/antiforgery", true);
    }
}
Run Code Online (Sandbox Code Playgroud)

并且您的/error/antiforgery观点可以告诉他们抱歉您尝试过两次提交相同的信息

另一个想法是记录错误并将用户返回到登录屏幕:

创建一个HandleAntiforgeryTokenErrorAttribute覆盖OnException方法的类.

HandleAntiforgeryTokenErrorAttribute.cs:

public class HandleAntiforgeryTokenErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        filterContext.ExceptionHandled = true;
        filterContext.Result = new RedirectToRouteResult(
            new RouteValueDictionary(new { action = "Login", controller = "Account" }));
    }
}
Run Code Online (Sandbox Code Playgroud)

全局过滤器:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new HandleAntiforgeryTokenErrorAttribute()
            { ExceptionType = typeof(HttpAntiForgeryException) }
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

我还会使用一些工具来记录您的所有信息,因为登录是您的应用程序的关键部分

NLog用于关键应用程序异常(包括Web异常)的常规日志记录和电子邮件.

Elmah用于过滤和发送Web异常的电子邮件.

编辑: 你也可以看一个名为SafeForm的jQuery插件.链接

编辑:

我已经看到了关于这个的所有辩论,每个人对这个问题的观点都有有效的观点,我怎么看待它(取自owasp.org)

跨站点请求伪造(CSRF)是一种攻击,它迫使最终用户在其当前正在进行身份验证的Web应用程序上执行不需要的操作 ,CSRF攻击专门针对状态更改请求,而不是数据被盗.防伪令牌特定于"谁登录".因此,一旦您登录,然后返回,旧令牌不再有效

现在,如果用户IP地址发生变化,我还使用授权的IP地址登录我的应用程序,并使用2因素授权,因此如果跨站点请求伪造正在进行中,则用户将无法匹配IP地址并请求2因素授权.几乎像安全路由器的工作方式.但是如果你想把它保存在你的登录页面上我没有看到问题,只要你设置了友好的错误页面,人们就不会感到不安,因为他们会看到他们做错了什么.