为什么Express / Connect为每个请求生成新的CSRF令牌?

据我所知,有两种方法可以防止CSRF攻击:1) 每个会话令牌 ,2) 每个请求令牌

1)在第一种情况下,当用户会话初始化时,CSRF令牌只生成一次。 所以一次只有一个用户有效的令牌。

2)在第二种情况下,每个请求都会生成一个新的CSRF令牌,之后一个旧的无效。 由于攻击者窃取令牌(通过XSS) ,当用户转到下一页时,就会过期,从而使得难度更大。 但另一方面,这种方法使webapp不太可用。 这里有一个很好的来自security.stackexchange.com的引用:

例如,如果他们点击“后退”button,并提交新的值的forms,提交将失败,并可能用一些敌对的错误信息迎接他们。 如果他们尝试在第二个选项卡中打开资源,他们会发现会话在一个或两个选项卡中随机分配

在分析Node.js Express框架(基于Connect )的时候,我发现每个请求都会生成一个新的CSRF标记, 但是旧的标记不会失效

我的问题是 :为什么要在每个请求中提供新的CSRF标记,而不是使旧的无效? 为什么不只是每个会话生成一个令牌?

谢谢你,对不起我的英文!

CSRF令牌是随机的。 他们应该只使用一次(或长时间安全)。 它们被用来识别和授权请求。 让我们考虑两种防止CSRF的方法:

  1. 每个会话固定的单个令牌:其缺点是客户端可以将令牌传递给其他人。 这可能不是由于嗅探,中间人或安全失误。 这是用户方面的背叛。 多个客户端可以使用相同的标记。 可悲的是没有办法做到这一点。

  2. dynamic令牌:每次在服务器和客户端之间发生任何交互或每当发生超时时都会更新令牌。 它防止使用旧的令牌,并同时使用多个客户端。

dynamic令牌的缺点是它限制了返回并从那里继续。 在某些情况下,它可能是可取的,就像实施购物车,重新加载是必须检查是否有货。 CSRF将防止重新发送发送的表单或重复购买/销售。

细粒度的控制会更好。 对于你提到的情况,你可以做没有CSRFvalidation。 那么不要使用CSRF的特定页面。 换句话说,处理每个路由的CSRF(或其例外)。

更新

我只能想到为什么单个dynamic令牌比多个要好的两个原因:

  1. 多个令牌确实比较好,但至less有一个dynamic令牌,就像上面的令牌一样。 这意味着devise一个可能变得复杂的详细工作stream程。 例如在这里看到:

    1. https://developers.google.com/accounts/docs/OAuth2
    2. https://dev.twitter.com/docs/auth/implementing-sign-twitter
    3. https://developers.facebook.com/docs/facebook-login/access-tokens/

    这些是令牌访问他们的API(表单提交等),而不仅仅是login。 每个人都有不同的实现。 除非有好的用例,否则不值得去做。 您的网页将大量使用它。 更何况现在表单提交并不简单。

  2. dynamic单个令牌是最简单的,并且在库中很容易获得。 所以可以在旅途中使用它。

多个令牌的优点:

  1. 可以实现交易。 您可以在请求之间进行sorting。
  2. 可以从超时和身份validation错误回退(您现在必须处理它们)。
  3. 安全! 比单个令牌更强大。 可以检测令牌滥用,黑名单用户。

顺便说一句,如果你想使用多个令牌,你现在有OAuth2库。