我目前正在表单中生成CSRF
令牌,以防止跨站点请求伪造。它看起来像:
<form method="post" action="action.php">
<input type="hidden" id="security_token" name="security_token" value="gTt96phAcretR99rafEjepHebrEZadEdezadagaZ3gAS5es33WReJeZaMADU2AWr" />
...
</form>
问题是我在一个页面上有多个表单。我必须为每个表单创建一个安全令牌security_token_1
,security_token_2
,或者我可以简单地在表单内部生成安全令牌,将其附加到整个body
标记的属性中像:
<body data-csrf-token="gTt96phAcretR99rafEjepHebrEZadEdezadagaZ3gAS5es33WReJeZaMADU2AWr">
...
</body>
这种不安全吗?它简化了一些事情,因为我可以简单地将安全令牌附加到body元素,而不是处理多个安全令牌。
感谢您的见解和评论。
答案 0 :(得分:15)
确实没有任何理由不能为两个表单生成相同的生成标记,每个表单中的每个隐藏字段都具有相同的name
属性。
毕竟,您真正想要验证的是表单请求是来自具有有效会话的用户的入站,并且一次只能主动发布一个表单。因此,您将比较针对用户存储在会话中的令牌发布的令牌。为了做到这一点,不需要有多个令牌值。
对于需要根据AJAX帖子更新令牌的情况,正如您所说,您需要做的是将新创建的令牌传回AJAX响应中,然后将隐藏字段值更新为新令牌值。
答案 1 :(得分:2)
只要您确保攻击者无法获取CSRF令牌(例如,不要将其包含在转发给第三方的表单中),使用单个CSRF令牌就可以了。请注意,使用“将其置于正文”方法后,您将需要JavaScript来提交表单,因此即使您只使用一个中央令牌,您仍可能希望将其插入到每个表单中。
通常,开发人员只需为当前会话生成一次此令牌。在初始生成此令牌后,该值将存储在会话中,并用于每个后续请求,直到会话到期为止。
即。根本不需要使用多个令牌。
使用单独的令牌只是有一个优势,如果你以某种方式设法妥协一些但不是全部(非常不可能,因为例如XSS会危及所有这些),攻击者的选择将是有限的。