防伪令牌适用于用户"",但当前用户是"用户名"

par*_*ent 122 membership-provider asp.net-mvc-4

我正在构建单页面应用程序并遇到防伪令牌问题.

我知道为什么问题发生我只是不知道如何解决它.

发生以下情况时,我收到错误消息:

  1. 未登录用户加载对话框(带有生成的防伪标记)
  2. 用户关闭对话框
  3. 用户登录
  4. 用户打开相同的对话框
  5. 用户在对话框中提交表单

防伪令牌适用于用户"",但当前用户是"用户名"

发生这种情况的原因是因为我的应用程序是100%单页,并且当用户通过ajax帖子成功登录时/Account/JsonLogin,我只是使用从服务器返回的"已验证视图"切换出当前视图但不重新加载页.

我知道这就是原因,因为如果我在步骤3和4之间简单地重新加载页面,就没有错误.

所以似乎@Html.AntiForgeryToken()在加载的表单中仍然为旧用户返回一个令牌,直到重新加载页面.

如何更改@Html.AntiForgeryToken()为新的经过身份验证的用户返回令牌?

我注入了新的GenericalPrincipal带有自定义IIdentity每个Application_AuthenticateRequest这样的时候@Html.AntiForgeryToken()被调用HttpContext.Current.User.Identity,其实我与自定义标识IsAuthenticated属性设置为true,但@Html.AntiForgeryToken似乎仍然呈现为老用户令牌,除非我做一个页面重新加载.

epi*_*isx 164

发生这种情况是因为防伪令牌将用户的用户名作为加密令牌的一部分嵌入,以便更好地进行验证.当您第一次调用时,@Html.AntiForgeryToken()用户未登录,因此令牌将具有用户名的空字符串,在用户登录后,如果您不替换防伪令牌,则它将不会通过验证,因为初始令牌是匿名用户,现在我们有一个具有已知用户名的经过身份验证的用户.

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

  1. 就在这个时候让你的SPA做一个完整的POST,当页面重新加载时,它将有一个防伪标记,嵌入了更新的用户名.

  2. @Html.AntiForgeryToken()在登录后使用正确和正确的部分视图,执行另一个AJAX请求并使用请求的响应替换现有的防伪标记.

  3. 只需禁用防伪验证执行的身份检查即可.将以下内容添加到Application_Start方法中:AntiForgeryConfig.SuppressIdentityHeuristicChecks = true.

  • @parliament:您接受了这个答案,您能与我们分享您选择的选项吗? (21认同)
  • 选项3对我不起作用.退出后,我在登录页面上打开了两个窗口.在一个窗口中以一个用户身份登录,然后在另一个窗口中以另一个用户身份登录并收到相同的错误. (18认同)
  • 良好而简单的选项+1.OAuth提供商的定时注销也会导致此问题. (9认同)
  • 选项3对我来说也不起作用.仍然得到同样的错误. (7认同)
  • 不幸的是,我无法得到一个很好的解决方案.我从登录页面中删除了令牌.登录后我仍然将它包含在帖子中. (5认同)
  • 选项3是啊+1.我很难弄清楚我的网站上发生了什么.切换用户或注销会导致此错误,但是当我刷新它消失时.EHH.谢谢.这解决了它. (3认同)
  • 应该从这个答案中删除#3.它并不禁用隐含的标识检查.请参阅http://www.asp.net/mvc/overview/security/xsrfcsrf-prevention-in-aspnet-mvc-and-web-pages`如果此值为true,系统将假定IIdentity.Name适用于用作唯一的每用户标识符,不会尝试特殊情况IClaimsIdentity` (3认同)
  • @McGaz - 很好的捕捉.你找到了解决方案吗?遇到同样的问题. (2认同)
  • 选项3对我也不起作用.但是选项2运作得非常好.我在文档加载上调用$ .get()并每次重新加载令牌.该错误仅在登录页面上发生.用户将登录,单击返回,然后再次登录.这就是造成它的原因. (2认同)

小智 21

要修复错误,您需要将OutputCache数据注释放在"获取ActionResult登录"页面上:

[OutputCache(NoStore=true, Duration = 0, VaryByParam= "None")] 
public ActionResult Login(string returnUrl)
Run Code Online (Sandbox Code Playgroud)

  • 为什么这个解决问题? (4认同)
  • 这解决了我的问题,完全有道理.谢谢! (3认同)

A. *_*rel 15

当您已通过身份验证登录时,将显示该消息。

这个 Helper 做的事情和[ValidateAntiForgeryToken]属性完全一样。

System.Web.Helpers.AntiForgery.Validate()
Run Code Online (Sandbox Code Playgroud)

[ValidateAntiForgeryToken]从控制器中删除属性并将此助手置于操作方法中。

因此,当用户已经通过身份验证时,重定向到主页,否则在此验证后继续验证有效的防伪令牌。

if (User.Identity.IsAuthenticated)
{
    return RedirectToAction("Index", "Home");
}

System.Web.Helpers.AntiForgery.Validate();
Run Code Online (Sandbox Code Playgroud)

要尝试重现该错误,请按以下步骤操作: 如果您在登录页面上并且未通过身份验证。如果您复制该选项卡并使用第二个选项卡登录。如果您返回登录页面的第一个选项卡,并尝试在不重新加载页面的情况下登录……您会遇到此错误。

  • 优秀的解决方案!在尝试了很多其他不起作用的建议后,这解决了我的问题。首先,重现错误是一件很痛苦的事情,直到我发现这可能是因为两个浏览器或选项卡打开了同一页面,并且用户从一个浏览器或选项卡登录,然后从第二个浏览器或选项卡登录而无需重新加载。 (2认同)

Ric*_*nça 10

我的应用程序发生了很多次,所以我决定谷歌吧!

我找到了关于这个错误的简单解释!用户双击登录按钮!您可以在下面的链接中看到另一位用户正在谈论这个问题:

MVC 4提供的防伪令牌是针对用户""但当前用户是"用户"

我希望它有所帮助!=)


小智 8

我遇到了同样的问题,这个肮脏的hack至少在我可以更干净的方式解决之前就将其修复。

    public ActionResult Login(string returnUrl)
    {
        if (AuthenticationManager.User.Identity.IsAuthenticated)
        {
            AuthenticationManager.SignOut();
            return RedirectToAction("Login");
        }
Run Code Online (Sandbox Code Playgroud)

...


归档时间:

查看次数:

76005 次

最近记录:

7 年,1 月 前