vto*_*ola 34 security asp.net-mvc csrf antiforgerytoken asp.net-mvc-3
我有反CRSF MVC机制的问题.cookie和返回的表单输入不匹配.我每次都会收到一个错误,只在一个特定的页面中.在应用程序的其余部分,它运行良好.
服务器正在返回HTTP 500 Internal Server Error,我可以在日志中看到此异常:
[System.Web.Mvc.HttpAntiForgeryException]:{"未提供所需的防伪标记或无效."}
这是服务器生成的隐藏输入:
<input name="__RequestVerificationToken" type="hidden" value="QK8P7rjyZE6Vm5seY7Fr704YCOoFGdTIMzl1W7R0ZFpXSMjGKLG2T05DfFSYTxvtQCEx7DDT69DGsDB2+ZXFHY8oAjiKz0gw8BhDFywgmfIpoXnGpj7fONNzIIfvbrDrE9WJsMu6Io/0bDLM5WfKs0zktiNjyOWpfYrmnfINYmjW8NLOZFoz74xTcgTptAld">
Run Code Online (Sandbox Code Playgroud)
这是Cookie返回:
Set-Cookie:__RequestVerificationToken_L2VGbG93=skmTAVI8HCbfxDS+xhioIMIISL3UOBI7qJM1JbHjTtAqKl4W70pDUcTKMm0p3R3mrHDziE8vXw0C0OO4HArzWO1/e6py+v/cFdbe9maFgjl4jMiZ9Wc4YIhC6+IUXkk6yqJDJ8dCIr8qtGaYcD9IX+m7/SlVhu521KQSWJYRcaY=; path=/; HttpOnly
Run Code Online (Sandbox Code Playgroud)
当我检查服务器发送的内容时,cookie完全相同,但我认为有效负载具有不同的编码:
__RequestVerificationToken:QK8P7rjyZE6Vm5seY7Fr704YCOoFGdTIMzl1W7R0ZFpXSMjGKLG2T05DfFSYTxvtQCEx7DDT69DGsDB2%2BZXFHY8oAjiKz0gw8BhDFywgmfIpoXnGpj7fONNzIIfvbrDrE9WJsMu6Io%2F0bDLM5WfKs0zktiNjyOWpfYrmnfINYmjW8NLOZFoz74xTcgTptAld
Run Code Online (Sandbox Code Playgroud)
区别在于两个出现编码的字符:
/ -> %2F
+ -> %2B
Run Code Online (Sandbox Code Playgroud)
这些是我在隐藏输入字段和后有效负载之间可以找到的唯一差异.
什么可能是导致ValidateAntiForgeryToken验证令牌失败的问题?
问候.
Sco*_*pey 77
我最近已经解决了几个问题ValidateAntiForgeryToken,所以我会和你分享我的发现.
Salt:既然你提到这只发生在一个页面上,我最好的猜测是你salt在调用Html.AntiForgeryToken(salt)和ValidateAntiForgeryToken(salt)调用时使用不同的值.
AJAX:正如另一个答案所说,使用AJAX可能需要额外的工作来确保令牌包含在POST中.这是我最喜欢的简单自动解决方案,可以将令牌添加到所有AJAX POST请求中.
但是,在您的问题中,您声明您已验证令牌正在发送.您是否确认过您只发送一次令牌?我发现我的一个AJAX调用是两次发送令牌,它组合了这些值,并导致它失败.
机器密钥和Cookie:这个问题很难看,容易发现(导致异常),但不是很直观.验证cookie和令牌使用唯一的"机器密钥"进行编码和解码.这意味着,如果您有服务器场或更改服务器,则您的cookie将不再有效.关闭浏览器可以解决问题(因为cookie是会话cookie).但是,有些人长时间在后台打开浏览器窗口!
解决方案是在配置文件中设置"机器密钥".这将告诉MVC在所有服务器上使用相同的密钥,确保cookie在任何地方都可以解密.
编码错误:使用名为jMeter的测试实用程序,我们尝试加载测试我们的页面,但发现它有一个错误导致我们的令牌"在值周围有2个额外的.
解决方案是降低您对工具的信任!在浏览器中进行测试,如果可行,则创建一个提取令牌和cookie值的测试,并设置断点以验证结果.
如果这些都不适合你,那么我建议你看一下MVC的源代码ValidateAntiForgeryTokenAttribute,特别是OnAuthorization方法.它将帮助您查看验证失败的不同步骤.您甚至可以检查错误Exception.StackTrace以确定哪个部件出现故障.
作为旁注,我真的不喜欢ValidateAntiForgeryTokenMVC中的实现,因为:
Page并创建一个人工ViewState来加密令牌和cookie.似乎矫枉过正.所以,我抓住了源代码,并创建了我自己的专用子类,这也证明在调试问题时非常有帮助,因为我可以在验证方法上设置断点,并且很容易确定哪个验证步骤失败了.