RequestVerificationToken 不匹配 [英] RequestVerificationToken does not match

查看:47
本文介绍了RequestVerificationToken 不匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对反 CRSF MVC 机制有疑问.cookie 和返回的表单输入不匹配.我每次都遇到错误,仅在一个特定页面中.在应用程序的其余部分,它运行良好.

服务器正在返回HTTP 500 Internal Server Error,我可以在日志中看到这个异常:

<块引用>

[System.Web.Mvc.HttpAntiForgeryException]: {"需要防伪令牌未提供或无效."}

这是服务器生成的隐藏输入:

 <代码><输入名称= __ RequestVerificationToken" 类型= 隐藏的" 值= QK8P7rjyZE6Vm5seY7Fr704YCOoFGdTIMzl1W7R0ZFpXSMjGKLG2T05DfFSYTxvtQCEx7DDT69DGsDB2 + ZXFHY8oAjiKz0gw8BhDFywgmfIpoXnGpj7fONNzIIfvbrDrE9WJsMu6Io/0bDLM5WfKs0zktiNjyOWpfYrmnfINYmjW8NLOZFoz74xTcgTptAld" >

这是返回的 Cookie:

<预> <代码>的Set-Cookie:__ RequestVerificationToken_L2VGbG93 = skmTAVI8HCbfxDS + xhioIMIISL3UOBI7qJM1JbHjTtAqKl4W70pDUcTKMm0p3R3mrHDziE8vXw0C0OO4HArzWO1/e6py + V/cFdbe9maFgjl4jMiZ9Wc4YIhC6 + IUXkk6yqJDJ8dCIr8qtGaYcD9IX + M7/SlVhu521KQSWJYRcaY =;路径=/;仅Http

当我检查服务器发送的内容时,cookie 完全相同,但我认为有效负载具有不同的编码:

 <代码> __ RequestVerificationToken:QK8P7rjyZE6Vm5seY7Fr704YCOoFGdTIMzl1W7R0ZFpXSMjGKLG2T05DfFSYTxvtQCEx7DDT69DGsDB2%2BZXFHY8oAjiKz0gw8BhDFywgmfIpoXnGpj7fONNzIIfvbrDrE9WJsMu6Io%2F0bDLM5WfKs0zktiNjyOWpfYrmnfINYmjW8NLOZFoz74xTcgTptAld

不同之处在于出现编码的两个字符:

/->%2F+ ->%2B

这些是我能找到的隐藏输入字段和帖子有效负载之间的唯一区别.

可能是什么问题导致 ValidateAntiForgeryToken 无法验证令牌?

问候.

解决方案

我最近遇到并解决了 ValidateAntiForgeryToken 的几个问题,所以我将与您分享我的发现.

Salt:由于您提到这仅发生在单个页面上,我最好的猜测是您在对 Html 的调用中使用了不同的 salt 值.AntiForgeryToken(salt)ValidateAntiForgeryToken(salt) 调用.

AJAX:正如另一个答案所说,使用 AJAX 可能需要额外的工作来确保令牌包含在 POST 中.这是我最喜欢的简单、自动的解决方案,用于将令牌添加到所有 AJAX POST 请求.
不过,在您的问题中,您声明您已验证令牌正在发送.您确认您只发送一次令牌吗?我发现我的一个 AJAX 调用发送了两次令牌,将这些值组合在一起,并导致它失败.

Machine Key and Cookies:这个问题很难看,很容易发现(导致异常),但不是很直观.验证 cookie 和令牌使用唯一的机器密钥"进行编码和解码.这意味着如果您有一个服务器群,或更改您的服务器,您的 cookie 将不再有效.关闭浏览器可以解决问题(因为 cookie 是会话 cookie).但是,有些人会在后台长时间打开浏览器窗口!
解决方案是在您的配置文件中设置一个机器密钥".这将告诉 MVC 在所有服务器上使用相同的密钥,确保 cookie 可以在任何地方解密.

编码错误:使用名为 jMeter 的测试实用程序,我们尝试加载测试我们的页面,结果发现它有一个错误导致我们的令牌有 2 个额外的 " 在值周围.
解决方案是降低您对工具的信任度!在浏览器中进行测试,如果可行,请创建一个测试来提取令牌和 cookie 值,并设置断点以验证结果.

如果这些东西都不适合你,那么我建议你看看 ValidateAntiForgeryTokenAttribute 的 MVC 源代码,特别是 OnAuthorization 方法.它将帮助您了解验证可能失败的不同步骤.您甚至可以检查错误的 Exception.StackTrace 以确定哪个部分出现故障.

顺便说一句,我真的不喜欢MVC中ValidateAntiForgeryToken的实现,因为:

  • 大约有 5 个验证步骤可能会失败,但只有一个通用错误消息.
  • 该类是密封的,因此无法使用其他功能对其进行扩展.
  • 加密方法很奇怪 - 它初始化一个 Page 并创建一个人工的 ViewState 来加密令牌和 cookie.似乎有点矫枉过正.

所以,我抓取了源代码,并创建了我自己的专用子类,结果证明这对调试问题也很有帮助,因为我可以在验证方法上设置断点,而且很容易确定哪个验证步骤失败.

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.

The server is returning HTTP 500 Internal Server Error and I can see on the log this exception:

[System.Web.Mvc.HttpAntiForgeryException]: {"A required anti-forgery token was not supplied or was invalid."}

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:

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:

__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 ValidateAntiForgeryToken fails in verify the token?

Regards.

解决方案

I've had and resolved several issues with ValidateAntiForgeryToken lately, so I'll share my findings with you.

Salt: Since you mention this only happens on a single page, my best guess is that you are using different salt values in your calls to Html.AntiForgeryToken(salt) and ValidateAntiForgeryToken(salt) calls.

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.

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.

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.

If none of these things work for you, then I'd recommend taking a look at the MVC source code for ValidateAntiForgeryTokenAttribute, specifically the OnAuthorization method. It will help you see the different steps where validation could fail. You might even inspect your error's Exception.StackTrace to determine which part is failing.

As a side note, I really dislike the implementation of ValidateAntiForgeryToken in MVC, because:

  • 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 Page and creates an artificial ViewState to encrypt the tokens and cookies. Seems overkill.

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.

这篇关于RequestVerificationToken 不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆