浏览器上的防伪令牌问题返回并重新提交
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参考。
在我的 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参考。