asp.net-mvc - 请求验证 token 不匹配

标签 asp.net-mvc asp.net-mvc-3 security csrf antiforgerytoken

我对反 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/

相关文章:

jQuery AJAX 可以返回 mvc 3 部分 View ,但 jQuery load 不能

c# - MVC 3 自定义数据注释 : associate error message with particular property

asp.net-mvc-3 - 在部分 View 中获取 viewdatadictionary 值

ASP.NET MVC - Ajaxified RenderAction

jquery - 至少选择一个复选框 - Asp.Net MVC - jQuery

security - HttpSession 安全

php - 如何一次仅从一台计算机使用一个 ID/通行证登录

php - Zend_Auth setCredentialTreatment

c# - ASP.net - cooking 食谱后的 Orchard CMS 'hangs'

asp.net - IIS7-请求过滤模块配置为拒绝超过请求内容长度的请求