使用 MVC2 的 AJAX 请求中的 CSRF 保护
我正在构建的页面很大程度上依赖于 AJAX。基本上,只有一个“页面”,并且每次数据传输都是通过 AJAX 处理的。由于浏览器端过度乐观的缓存会导致奇怪的问题(数据未重新加载),因此我必须使用 POST 执行所有请求(也读取) - 这会强制重新加载。
现在我想阻止针对CSRF的页面。通过表单提交,使用 Html.AntiForgeryToken()
可以很好地工作,但是在 AJAX 请求中,我想我必须手动附加令牌?有什么开箱即用的东西吗?
我当前的尝试如下:
我很乐意重用现有的魔法。但是,HtmlHelper.GetAntiForgeryTokenAndSetCookie
是私有的,我不想在 MVC 中进行修改。另一种选择是编写一个扩展,这样
public static string PlainAntiForgeryToken(this HtmlHelper helper)
{
// extract the actual field value from the hidden input
return helper.AntiForgeryToken().DoSomeHackyStringActions();
}
有点hacky并且留下了未解决的更大问题:如何验证该令牌?默认验证实现是内部的,并且针对使用表单字段进行了硬编码。我尝试编写一个稍微修改过的 ValidateAntiForgeryTokenAttribute,但它使用了一个私有的 AntiForgeryDataSerializer,我真的不想复制它。
在这一点上,提出一个自行开发的解决方案似乎更容易,但这实际上是重复的代码。
有什么建议如何以聪明的方式做到这一点?我错过了一些完全明显的东西吗?
The page I'm building depends heavily on AJAX. Basically, there is just one "page" and every data transfer is handled via AJAX. Since overoptimistic caching on the browser side leads to strange problems (data not reloaded), I have to perform all requests (also reads) using POST - that forces a reload.
Now I want to prevent the page against CSRF. With form submission, using Html.AntiForgeryToken()
works neatly, but in AJAX-request, I guess I will have to append the token manually? Is there anything out-of-the box available?
My current attempt looks like this:
I'd love to reuse the existing magic. However, HtmlHelper.GetAntiForgeryTokenAndSetCookie
is private and I don't want to hack around in MVC. The other option is to write an extension like
public static string PlainAntiForgeryToken(this HtmlHelper helper)
{
// extract the actual field value from the hidden input
return helper.AntiForgeryToken().DoSomeHackyStringActions();
}
which is somewhat hacky and leaves the bigger problem unsolved: How to verify that token? The default verification implementation is internal and hard-coded against using form fields. I tried to write a slightly modified ValidateAntiForgeryTokenAttribute
, but it uses an AntiForgeryDataSerializer
which is private and I really didn't want to copy that, too.
At this point it seems to be easier to come up with a homegrown solution, but that is really duplicate code.
Any suggestions how to do this the smart way? Am I missing something completely obvious?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以使用传统的
Html.AntiForgeryToken()
帮助程序在页面上的某个位置(不一定在表单内)生成隐藏字段,并将其包含在 ajax 请求中:要在服务器端验证它:
如果您的页面上有多个令牌,您可能需要指定要包含哪一个。由于现有的帮助器生成具有相同名称的隐藏字段,因此很难制作一个好的选择器,因此您可以将它们放在 spans: 内,
然后选择相应的标记:
You could use the conventional
Html.AntiForgeryToken()
helper to generate a hidden field somewhere on the page (not necessarily inside a form) and include it along the ajax request:To verify it on the server side:
If you have multiple tokens on your page you might need to specify which one to include. As the existing helper generates the hidden fields with the same names it is difficult to make a good selector so you could place them inside spans:
and then select the corresponding token: