我对反 CRSF MVC 机制有疑问。返回的 cookie 和表单输入不匹配。我每次都会收到错误,仅在一个特定页面中。在应用程序的其余部分中,它运行良好。
服务器正在返回HTTP 500内部服务器错误
,我可以在日志中看到此异常:
[System.Web.Mvc.HttpAntiForgeryException]: {"A required anti-forgery token was not supplied or was invalid."}
这是服务器生成的隐藏输入:
<input name="__RequestVerificationToken" type="hidden" value="QK8P7rjyZE6Vm5seY7Fr704YCOoFGdTIMzl1W7R0ZFpXSMjGKLG2T05DfFSYTxvtQCEx7DDT69DGsDB2+ZXFHY8oAjiKz0gw8BhDFywgmfIpoXnGpj7fONNzIIfvbrDrE9WJsMu6Io/0bDLM5WfKs0zktiNjyOWpfYrmnfINYmjW8NLOZFoz74xTcgTptAld">
这是返回的 Cookie:
Set-Cookie:__RequestVerificationToken_L2VGbG93=skmTAVI8HCbfxDS+xhioIMIISL3UOBI7qJM1JbHjTtAqKl4W70pDUcTKMm0p3R3mrHDziE8vXw0C0OO4HArzWO1/e6py+v/cFdbe9maFgjl4jMiZ9Wc4YIhC6+IUXkk6yqJDJ8dCIr8qtGaYcD9IX+m7/SlVhu521KQSWJYRcaY=; path=/; HttpOnly
当我检查服务器发送的内容时,cookie 完全相同,但我认为有效负载具有不同的编码:
__RequestVerificationToken:QK8P7rjyZE6Vm5seY7Fr704YCOoFGdTIMzl1W7R0ZFpXSMjGKLG2T05DfFSYTxvtQCEx7DDT69DGsDB2%2BZXFHY8oAjiKz0gw8BhDFywgmfIpoXnGpj7fONNzIIfvbrDrE9WJsMu6Io%2F0bDLM5WfKs0zktiNjyOWpfYrmnfINYmjW8NLOZFoz74xTcgTptAld
差异在于两个编码字符:
/ -> %2F
+ -> %2B
这些是我能在隐藏输入字段和帖子有效负载之间找到的唯一区别。
导致 ValidateAntiForgeryToken
验证 token 失败的问题可能是什么?
问候。
最佳答案
我最近遇到并解决了 ValidateAntiForgeryToken
的几个问题,因此我将与您分享我的发现。
盐:由于您提到这只发生在单个页面上,所以我最好的猜测是您在对 Html 的调用中使用了不同的
和 salt
值。 AntiForgeryToken(salt)ValidateAntiForgeryToken(salt)
调用。
AJAX:正如另一个答案所说,使用 AJAX 可能需要额外的工作来确保 token 包含在 POST 中。这是我最喜欢的simple, automatic solution to add the token to all AJAX POST requests .
但在您的问题中,您声明您已验证 token 正在发送。您是否已确认只发送 token 一次?我发现我的 AJAX 调用发送了两次 token ,这合并了值,并导致它失败。
机器 key 和 Cookie:这个问题很难看,很容易发现(导致异常),但不太直观。验证 cookie 和 token 使用唯一的“机器 key ”进行编码和解码。这意味着,如果您有服务器场,或者更改了服务器,您的 cookie 将不再有效。关闭浏览器可以解决该问题(因为 cookie 是 session cookie)。然而,有些人将浏览器窗口长时间在后台打开!
解决方案是在配置文件中设置“机器 key ”。这将告诉 MVC 在所有服务器上使用相同的 key ,确保 cookie 在任何地方都可以解密。
编码错误:使用名为 jMeter 的测试实用程序,我们尝试对页面进行负载测试,结果发现它有一个错误,导致我们的 token 有 2 个额外的 ”
围绕值。
解决方案是降低对工具的信任!在浏览器中进行测试,如果有效,则创建一个提取 token 和 cookie 值的测试,并设置断点来验证结果。
如果这些方法都不适合您,那么我建议您查看 the MVC source code for ValidateAntiForgeryTokenAttribute
,特别是 OnAuthorization
方法。它将帮助您了解验证可能失败的不同步骤。您甚至可以检查错误的 Exception.StackTrace 以确定哪个部分出现故障。
顺便说一句,我真的不喜欢 MVC 中 ValidateAntiForgeryToken
的实现,因为:
- 大约有 5 个验证步骤可能会失败,但只有一条一般错误消息。
- 该类是密封的,因此无法使用其他功能进行扩展。
- 加密方法很奇怪 - 它初始化一个
Page
并创建一个人工ViewState
来加密 token 和cookie。似乎有点过分了。
因此,我获取了源代码,并创建了自己的专用子类,这对于调试其问题也非常有帮助,因为我可以在验证方法上设置断点,并且很容易确定哪个验证步骤失败。
关于asp.net-mvc - 请求验证 token 不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7766975/