我正在尝试集成一种方法,为我的应用程序中的每个表单添加一个哈希标记。我想通过这个实现目标:
现在,我想这样做的概念应该很简单:
到目前为止一切顺利,现在我真正陷入困境的是以下情况:
如果用户使用我的应用程序打开另一个选项卡,该怎么办?每次加载页面时,都会重新生成哈希值。因此,从第一个选项卡中的表单呈现哈希值无效。
答案 0 :(得分:2)
不要将令牌存储为cookie。
在每个页面展示上生成唯一标记。在POST时,验证您是否已向该用户发出令牌并验证它之前是否已被使用过。
首先,我们生成一个令牌,我们可以验证我们是否为给定用户发布了它:
token = hash(session_id + secret)
这样,使用他们的会话ID和我们的秘密,我们总能验证我们发出了这个令牌,因为没有人知道秘密。
现在我们需要确保令牌只能使用一次。
rnd = rand()
token = rnd + hash(session_id + secret + rnd)
令牌现在有一个随机数。发生POST时,我们可以将此随机数存储为“之前已使用过”,并拒绝重新使用相同随机数的任何令牌。
但我们不想永久存储使用过的令牌的随机数。所以我们限制了令牌的生命周期。
rnd = rand()
now = time()
token = rnd + time + hash(session_id + secret + rnd + time)
在POST时,当我们获得令牌时,我们现在检查是否“最近”发出了令牌。我们只需要为相同的时间跨度存储使用过的随机数。根据定义,所有旧令牌都无效。
您可以保护使用的随机数以及会话ID,并在您逐出会话ID或将其变为无效时删除它们(以先发生者为准)。
答案 1 :(得分:1)
我会独立实现这些功能:
CSRF预防
使用CSRF令牌阻止成功的CSRF攻击:为每个会话或每个URL /表单生成随机令牌,并将其存储在会话中。最初请求表单时,请放置(关联的)CSRF令牌,并在处理提交的表单数据时对其进行验证。
由于CSRF令牌由服务器生成并存储在服务器上,因此攻击站点不能伪造它,并且仅对该会话有效。同样,验证也是微不足道的。唯一剩下的风险是攻击站点可以通过跨站点脚本获取已发布的CSRF令牌(但这会使CSRF在某种程度上过时)。
多表单提交预防
使用一次有效的令牌来阻止多次提交:为每个初始表单请求生成唯一标记并将其放在表单中。在表单提交时,检查该令牌是否已被使用并将其记住为已使用。
要仅允许服务器发布的令牌,您可以使用某种message authentication algorithm。要降低要记住的令牌数量,您可以让令牌在某个时间到期,这样您就必须记住特定时间范围内的令牌。
多个标签页或表单请求都没有问题:CSRF标记在整个会话期间或对特定URL /表单的任何表单提交都有效。另一个令牌仅对单个表单提交有效。