MVC 4中防伪cookie令牌和表单字段令牌不匹配

49

我正在使用ASP.NET MVC 4中的默认登录模块。我没有改变默认应用程序中的任何代码,并将其托管在共享服务器上。

在使用默认登录页面登录后,当我让浏览器闲置一段时间后,当我尝试执行任何带有[Authorize]属性的控制器操作时,应用程序显然会重定向到登录页面。

然后我尝试重新登录,但当我单击登录按钮时,它会出现错误。

The anti-forgery cookie token and form field token do not match.

输入图像描述

登录操作

// POST: /Account/Login

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Login(LoginModel model, string returnUrl)
        {
            if (ModelState.IsValid && WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
            {
                return RedirectToLocal(returnUrl);
            }

            // If we got this far, something failed, redisplay form
            ModelState.AddModelError("", "The user name or password provided is incorrect.");
            return View(model);
        }

你是否将防伪令牌放入表单中了? - ta.speot.is
2
共享主机可能会影响您的Cookie吗? AntiForgeryToken 为访问者提供名为 __RequestVerificationToken 的Cookie,并将其放置在页面上的隐藏字段中。当您调用服务器时,它会比较您在Cookie中拥有的值和与表单一起发送的任何内容。 - Artless
@ta.speot.is 我还没有在表单中添加它,因为它已经存在于控制器中。它需要出现在其中一个地方,是在表单中还是在控制器中? - chamara
该属性称为“ValidateAntiForgeryToken”。它验证“AntiForgeryToken”... - ta.speot.is
@ta.speot.is 对于我之前的评论感到抱歉。@Html.AntiForgeryToken() 在表单中是存在的。 - chamara
1
阅读此内容,可能对您有所帮助。https://dev59.com/pWsz5IYBdhLWcg3wn5Xa 和 https://dev59.com/5W025IYBdhLWcg3w1ZkL - Sampath
7个回答

50

我通过在web.config中显式添加机器密钥来解决了这个问题。

注意:出于安全原因,请勿使用此密钥。从https://support.microsoft.com/en-us/kb/2915218#AppendixA生成一个密钥。不要使用在线生成的密钥,详情请参见http://blogs.msdn.com/b/webdev/archive/2014/05/07/asp-net-4-5-2-and-enableviewstatemac.aspx

 <machineKey validationKey="971E32D270A381E2B5954ECB4762CE401D0DF1608CAC303D527FA3DB5D70FA77667B8CF3153CE1F17C3FAF7839733A77E44000B3D8229E6E58D0C954AC2E796B" decryptionKey="1D5375942DA2B2C949798F272D3026421DDBD231757CA12C794E68E9F8CECA71" validation="SHA1" decryption="AES" />

这里有一个可以生成独特机器密钥的网站:

http://www.developerfusion.com/tools/generatemachinekey/


10
这对我来说立刻解决了问题。请注意,这应该放在web.config文件的<system.web>标签中。 - JensB
24
希望你在应用中使用的不是真正的机器密钥,而是生成了一个新的 :-) - Darin Dimitrov
2
你好..我遇到了与OP描述相同的问题。我尝试了从这里http://aspnetresources.com/tools/machineKey获取一个密钥的解决方案,但并没有解决问题。唯一的区别是,我并不总是看到这个错误。我的网站托管在GoDaddy共享主机上。有什么想法吗? - Laurence
4
根据微软文档,生成机器密钥时不应使用第三方工具或网站,应该自己操作。请勿使用其他人制作的机器密钥。 - barnacle.m
5
您可以在IIS中通过单击任何网站,点击中间的“ASP.NET”部分下的“Machine Key”,然后在右侧点击“Generate Keys”来生成它们。 - computrius

11

出现此错误的另一个原因是,如果您在未被浏览器缓存的[Authorize]区域之间进行跳转(这可能是有意为之,以阻止用户在退出登录并使用后退按钮查看受保护的内容时发生)。

如果是这种情况,您可以使您的操作不被缓存,这样,如果有人单击后退按钮并最终停留在带有@Html.AntiForgeryToken()表单的页面上,则令牌将不会从先前缓存。

请参见此帖子,了解如何添加[NoCache] ActionFilterAttribute: 如何处理ASP.NET MVC后退按钮的表单提交?


3
扫描仪,你没有理解重点。Ctrl+F5确实可以清除缓存,但普通互联网用户可能不知道他们需要这样做,而且它本来就不应该发生。 - Yovav

3

请确保在页面的表单中加入@Html.AntiForgeryToken()。


3

我长期以来一直遇到这个问题,并认为这是ASP.NET出了问题。

实际上,是服务器的问题。当时我使用的是WinHost,他们有一个200MB的内存限制。一旦同时有约20个用户登录,我的限制就会达到。此时,每个人都被注销并出现这些问题。


3

对我来说,这是由于使用button标签提交表单引起的。将其更改为input submit标签可以解决此问题。


迈克上面的建议,再加上硬机器密钥对我很有帮助。在调试具有用户/密码登录的MVC4应用程序时,我一直遇到这个问题。 - ScottLenart
2
@Mike - 为什么 button 标签会引起这个问题,而 input 标签却不会? - Matt Shepherd

0
在我的情况下,“我们发现网站缓存已启用,由于这个“反伪造”令牌值不会在每次更新后更新,所以在移除了缓存后,表单才能提交。”

0
在我的情况下,这与域站点和子域站点设置的多个cookie值有关。
  • main.com设置__RequestVerificationToken = 1
  • sub.main.com设置__RequestVerificationToken = 2
但是,当发送到sub.main.com的请求时,它使用了来自main.com的__RequestVerificationToken = 1值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接