asp.net-mvc RequestVerificationToken 不匹配
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7766975/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
RequestVerificationToken does not match
提问by vtortola
I have a problem with the anti CRSF MVC mechanism. The cookie and the form input returned does not match. I'm getting an error every single time, only in one specific page. In the rest of the application it works well.
我对反 CRSF MVC 机制有问题。cookie 和返回的表单输入不匹配。我每次都遇到错误,仅在一个特定页面中。在应用程序的其余部分,它运行良好。
The server is returning HTTP 500 Internal Server Errorand I can see on the log this exception:
服务器正在返回HTTP 500 Internal Server Error,我可以在日志中看到此异常:
[System.Web.Mvc.HttpAntiForgeryException]: {"A required anti-forgery token was not supplied or was invalid."}
[System.Web.Mvc.HttpAntiForgeryException]:{“未提供所需的防伪令牌或无效。”}
This is the hidden input that the server is generating is:
这是服务器生成的隐藏输入:
<input name="__RequestVerificationToken" type="hidden" value="QK8P7rjyZE6Vm5seY7Fr704YCOoFGdTIMzl1W7R0ZFpXSMjGKLG2T05DfFSYTxvtQCEx7DDT69DGsDB2+ZXFHY8oAjiKz0gw8BhDFywgmfIpoXnGpj7fONNzIIfvbrDrE9WJsMu6Io/0bDLM5WfKs0zktiNjyOWpfYrmnfINYmjW8NLOZFoz74xTcgTptAld">
And this is the Cookie returned:
这是返回的 Cookie:
Set-Cookie:__RequestVerificationToken_L2VGbG93=skmTAVI8HCbfxDS+xhioIMIISL3UOBI7qJM1JbHjTtAqKl4W70pDUcTKMm0p3R3mrHDziE8vXw0C0OO4HArzWO1/e6py+v/cFdbe9maFgjl4jMiZ9Wc4YIhC6+IUXkk6yqJDJ8dCIr8qtGaYcD9IX+m7/SlVhu521KQSWJYRcaY=; path=/; HttpOnly
When I examine what the server is sending, the cookie is exactly the same, but the payload has different encoding I think:
当我检查服务器发送的内容时,cookie 完全相同,但我认为有效负载具有不同的编码:
__RequestVerificationToken:QK8P7rjyZE6Vm5seY7Fr704YCOoFGdTIMzl1W7R0ZFpXSMjGKLG2T05DfFSYTxvtQCEx7DDT69DGsDB2%2BZXFHY8oAjiKz0gw8BhDFywgmfIpoXnGpj7fONNzIIfvbrDrE9WJsMu6Io%2F0bDLM5WfKs0zktiNjyOWpfYrmnfINYmjW8NLOZFoz74xTcgTptAld
The differences are in two characters that appear encoded:
不同之处在于出现编码的两个字符:
/ -> %2F
+ -> %2B
Those are the only differences I can find between the hidden input field, and the post payload.
这些是我能找到的隐藏输入字段和帖子有效负载之间的唯一区别。
What could be the problem that is causing that ValidateAntiForgeryTokenfails in verify the token?
导致ValidateAntiForgeryToken验证令牌失败的问题可能是什么?
Regards.
问候。
回答by Scott Rippey
I've had and resolved several issues with ValidateAntiForgeryTokenlately, so I'll share my findings with you.
我最近遇到并解决了几个问题ValidateAntiForgeryToken,所以我将与您分享我的发现。
Salt: Since you mention this only happens on a single page, my best guess is that you are using different saltvalues in your calls to Html.AntiForgeryToken(salt)and ValidateAntiForgeryToken(salt)calls.
Salt:由于您提到这仅发生在单个页面上,我最好的猜测是您salt在对Html.AntiForgeryToken(salt)和 的ValidateAntiForgeryToken(salt)调用中使用了不同的值。
AJAX: as another answer has said, using AJAX may require extra work to ensure the token is included in the POST. Here is my favorite simple, automatic solution to add the token to all AJAX POST requests.
In your question though, you state that you have verified that the token is sending. Have you verified that you're only sending the token once? I found out that an AJAX call of mine was sending the token twice, which combined the values, and caused it to fail.
AJAX:正如另一个答案所说,使用 AJAX 可能需要额外的工作来确保令牌包含在 POST 中。这是我最喜欢的将令牌添加到所有 AJAX POST 请求的简单自动解决方案。
不过,在您的问题中,您声明您已验证令牌正在发送。您是否确认您只发送一次令牌?我发现我的一个 AJAX 调用发送了两次令牌,它组合了这些值,并导致它失败。
Machine Key and Cookies: this issue is ugly, easy to spot (causes exceptions), but not very intuitive. The validation cookies and tokens are encoded and decoded using a unique "machine key". This means that if you have a server farm, or change your server, your cookie will no longer be valid. Closing your browser fixes the issue (because the cookie is a session cookie). However, some people leave their browser windows open in the background for a long time!
The solution is to set a "machine key" in your config file. This will tell MVC to use the same key on all servers, ensuring that the cookie will be decryptable everywhere.
Machine Key and Cookies:这个问题很难看,很容易发现(导致异常),但不是很直观。验证 cookie 和令牌使用唯一的“机器密钥”进行编码和解码。这意味着如果您有一个服务器群,或更改您的服务器,您的 cookie 将不再有效。关闭浏览器可以解决问题(因为 cookie 是会话 cookie)。但是,有些人会在后台长时间打开浏览器窗口!
解决方案是在您的配置文件中设置一个“机器密钥”。这将告诉 MVC 在所有服务器上使用相同的密钥,确保 cookie 可以在任何地方解密。
Encoding Bugs: using a testing utility called jMeter, we attempted to load-test our pages, only to find out that it had a bug that caused our token to have 2 extra "around the value.
The solution is to lower your trust in your tools! Test in a browser, and if that works, create a test that extracts the token and cookie values, and set a breakpoint to verify the results.
编码错误:使用名为 jMeter 的测试实用程序,我们尝试对我们的页面进行负载测试,结果发现它有一个错误,导致我们的令牌"在值周围有 2 个额外的值。
解决方案是降低您对工具的信任度!在浏览器中测试,如果可行,创建一个测试来提取令牌和 cookie 值,并设置断点来验证结果。
If none of these things work for you, then I'd recommend taking a look at the MVC source code for ValidateAntiForgeryTokenAttribute, specifically the OnAuthorizationmethod. It will help you see the different steps where validation could fail. You might even inspect your error's Exception.StackTraceto determine which part is failing.
如果这些东西都不适合您,那么我建议您查看MVC 源代码ValidateAntiForgeryTokenAttribute,特别是OnAuthorization方法。它将帮助您了解验证可能失败的不同步骤。您甚至可以检查您的错误Exception.StackTrace以确定哪个部分出现故障。
As a side note, I really dislike the implementation of ValidateAntiForgeryTokenin MVC, because:
作为旁注,我真的不喜欢ValidateAntiForgeryToken在 MVC 中的实现,因为:
- There are about 5 verification steps that can fail, but there is only one generic error message.
- The class is sealed, so it cannot be extended with additional functionality.
- The encryption method is weird - it initializes a
Pageand creates an artificialViewStateto encrypt the tokens and cookies. Seems overkill.
- 大约有 5 个验证步骤可能会失败,但只有一个通用错误消息。
- 该类是密封的,因此不能使用附加功能对其进行扩展。
- 加密方法很奇怪 - 它初始化 a
Page并创建一个人工ViewState来加密令牌和 cookie。似乎矫枉过正。
So, I grabbed the source code, and created my own specialized subclass, which also turned out to be very helpful in debugging its issues, because I could set breakpoints on the validation methods, and it was really easy to determine which validation step was failing.
因此,我获取了源代码,并创建了自己的专用子类,结果证明这对调试问题也非常有帮助,因为我可以在验证方法上设置断点,而且很容易确定哪个验证步骤失败了.
回答by Skuld
If this is being sent as an Ajax request, then the current setup of the framework isn't build to do this naturally.
如果这是作为 Ajax 请求发送的,则框架的当前设置不会自然地执行此操作。
Luckly Phil Haak wrote a nice blog post on dealing with CSRF and Ajax -> Preventing CSRF With Ajaxwhich goes into some good detail about how to use the existing framework and modify it to work for Ajax/Json.
幸运的是,Phil Haak 写了一篇关于处理 CSRF 和 Ajax ->使用 Ajax 防止 CSRF的不错的博客文章,其中详细介绍了如何使用现有框架并将其修改为适用于 Ajax/Json。
回答by ComeIn
From my recent findings ...
从我最近的发现...
If you set content type as "application/x-www-form-urlencoded" in the ajax request then you must put the AFRT in the data
如果您在 ajax 请求中将内容类型设置为“application/x-www-form-urlencoded”,那么您必须将 AFRT 放入数据中
If you set the content type to "application/json" then the token goes in the ajax "headers" property as described by haack.
如果您将内容类型设置为“application/json”,那么令牌将进入 ajax 的“headers”属性,如 haack 所述。
On the server if you are checking for the form type token then using the vanilla AntiForgeryRequestTokenAttribute is ok but if you want to validate tokens sent in the header then you need to call the AntiForgeryToken.OnAuthorize ... or whatever, passing the token from the cookie (http context).
在服务器上,如果您正在检查表单类型令牌,那么使用 vanilla AntiForgeryRequestTokenAttribute 就可以了,但是如果您想验证在标头中发送的令牌,那么您需要调用 AntiForgeryToken.OnAuthorize ... 或其他方法,从cookie(http 上下文)。
It aint easy but if it was everybody would be doing it :)
这并不容易,但如果是每个人都会这样做:)

