6

我对网络安全相当陌生。我想知道在没有提交按钮(即状态更新)的情况下在 ajax 请求和表单上使用令牌以保护 CSRF 的正确方法是什么。有人可以给我看一个代码示例吗?我知道如何正确处理带有提交按钮的表单。同样在我的 ajax 文件夹中,我有一个带有以下内容的 htaccess:

SetEnvIfNoCase X-Requested-With XMLHttpRequest ajax
Order Deny,Allow
Deny from all
Allow from env=ajax

这对 ajax 请求是否足够安全,或者我也应该为 ajax 请求实现令牌安全性?

4

2 回答 2

10

您需要做的就是在页面加载时生成一个秘密(令牌)。将它放在页面上,并在会话中。通常,如果可以的话,我会将它作为隐藏字段放在表单中,或者如果它是一个更大的非常 ajaxy 页面的一部分,我会将它放在相关元素上的 value 属性中,比如包装整个页面的 div。其他人将添加一个带有变量集的脚本标签。

然后,每当您进行 AJAX 调用或发送表单时,都会包含一个密码字段。(Cheekysoft 的回答更详细地介绍了如何使用原始 JS 执行此操作,它可以与 jQuery 或您可能使用的任何其他框架大致相同。)将其与后端的会话值匹配以确保它们仍然存在相同(来自同一来源),你很好。

如果您想增加安全性,请在每个请求上重新生成密钥,并将该新密钥与请求的数据一起返回。让所有 ajax 请求用新值替换隐藏字段或值属性。如果您正在执行大量请求或并发请求,这并不能很好地工作。确实,如果您通过 HTTPS 执行此操作,则每次加载整个页面时生成一个就足够了,您应该这样做。

如果您不是通过 HTTPS 执行此操作,那真的没关系,坐在网吧/星巴克的人可以窃取会话并重新加载页面。

如果您要经常这样做,那么值得查看 jQuery 和各种有助于为您提供 CSRF 保护的插件。而且,我的方法不是唯一的方法。

于 2012-04-13T15:26:53.100 回答
2

如果您的 XHR 是 GET 请求,请将令牌作为 URL 参数包含并让 PHP 脚本从$_GET[]. 如果您的 XHR 是 POST,则将令牌弹出到 POST 数据中并让 PHP 脚本从$_POST[].

获取请求

var token = getElementById( 'myHiddenField' ).value;
var xhr = new XMLHttpRequest();
xhr.open( 'GET', 'server.php?token=' + token );
xhr.send( null );

POST 请求

var token = getElementById( 'myHiddenField' ).value;
var xhr = new XMLHttpRequest();
xhr.open( 'POST', 'server.php', true );
xhr.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
xhr.onreadystatechange = function() {
  if (xhreq.readystate != 4) { return; }
  // do client side stuff here
};
xhr.send( 'token=' + token );
于 2012-04-13T15:28:44.880 回答