浏览器上的防伪令牌问题返回并重新提交

anti-forgery token issue on browser back and resubmit

在我的 MVC5 应用程序中,实现了防伪令牌。当用户启动并登录时,它可以工作。如果用户在登录后单击浏览器返回并使用不同的凭据重新提交,它会显示

The provided anti-forgery token was meant for user "xxxx", but the current user is "yyyy"

在登录控制器中,我试过类似

public ActionResult Index()
{
    if (User != null && (User.Identity.IsAuthenticated || User.Identity.Name != ""))
    {
        FormsAuthentication.SignOut();
        Session.Abandon();
        return RedirectToAction("Index");
    }
    return View();
}

但是在这种情况下系统不会触发操作。

修饰您的登录 GET 方法
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public ActionResult Login(...)

防止页面被缓存。这将强制创建一个没有先前登录用户名的新令牌。

当我们有防伪令牌时,这很常见。

This is happening because the anti-forgery token embeds the username of the user as part of the encrypted token for better validation. When you first call the @Html.AntiForgeryToken() the user is not logged in so the token will have an empty string for the username, after the user logs in, if you do not replace the anti-forgery token it will not pass validation because the initial token was for anonymous user and now we have an authenticated user with a known username.

您有几个选项可以解决这个问题:

1- 就在这一次让您的应用程序做一个完整的 POST 并且当 页面重新加载它将具有更新后的防伪令牌 嵌入的用户名。

2- 仅使用@Html.AntiForgeryToken() 和右侧的部分视图 登录后,执行另一个 AJAX 请求并替换您现有的 带有请求响应的防伪令牌。

3- 仅禁用身份检查防伪验证 施行。将以下内容添加到您的 Application_Start 方法中: AntiForgeryConfig.SuppressIdentityHeuristicChecks = 真。

针对 AntiForgeryToken 运行的验证代码还会检查您的登录用户凭据是否已更改 – 这些也在 cookie 中加密。这意味着如果您在弹出窗口或其他浏览器选项卡中登录或注销,您的表单提交将失败并出现以下异常:

System.Web.Mvc.HttpAntiForgeryException (0x80004005):
The provided anti-forgery token was meant for user "xxxx", but the current user is "yyyy".

您可以通过设置 AntiForgeryConfig.SuppressIdentityHeuristicChecks = true 来关闭此功能;在 Global.asax 文件内的 Application_Start 方法中。

当 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);
    }
}

Here 是类似问题的 SO 线程。

additional参考。