在没有提交按钮的情况下对ajax请求和表单上的CSRF进行保护

时间:2012-04-13 15:12:39

标签: ajax security token csrf

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

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

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

2 个答案:

答案 0 :(得分:9)

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

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

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

如果你不是通过HTTPS做这件事,那真的没关系,坐在网吧/星巴克的人可以偷走会话并重新加载页面。

如果您打算这么做,那么值得查看jQuery和various plugins,这将有助于为您做CSRF保护。 Also, my way isn't the only way.

答案 1 :(得分: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 );