要防止CSRF,您应该将nonce放在表单中的隐藏字段中,以及cookie或会话变量中.但是如果用户在不同的标签页中打开多个页面会怎么样 在这种情况下,每个选项卡都有一个具有唯一nonce的表单,但会话变量或cookie中只存储一个nonce.或者,如果您尝试将所有nonce存储在cookie/session变量中,您将如何识别哪个属于哪个表单?
您可以在每个表单中存储相同的随机数.最简单的方法是将nonce与会话ID绑定,以便这些表单仅在该会话中起作用.
您将希望攻击者难以snarf会话ID并创建自己的nonce.因此,一种方法是使用HMAC-SHA256(或类似方法)来散列会话ID,使用您不向公众公开的密钥.
(显然,如果攻击者本身可以获得实际的会话ID,他们就已经可以进行会话劫持.所以这不是我所说的,而是攻击者制作脚本(在受害者的计算机上运行)的能力可以以某种方式获取会话ID并使用它来动态生成带有nonce预填充的URL.)
ETA:上述方法是否足够取决于您期望典型会话持续多长时间.如果用户通常使用持续时间超过几小时的长时间会话,则需要使用更复杂的内容.
一种方法是为每个表单创建一个新的nonce,其中包含时间戳,以及hash(timestamp . sessionid)
(hash
如上所述,HMAC的某些变体,以防止伪造,并且.
是字符串连接).然后通过以下方式验证nonce:
检查时间戳以确保nonce足够新鲜(这取决于您的策略,但通常是几个小时)
然后,根据时间戳和会话ID计算哈希值,并与nonce进行比较,以验证nonce是否是真实的
如果nonce检查失败,你将需要显示一个新的表单,预先填充用户的提交(如果他们花了一整天写他们的帖子,他们将不会失去他们所有的辛勤工作),以及作为一个新鲜的nonce.然后用户可以成功立即重新提交.