csurf 中间件如何验证令牌?

How csurf middleware validates tokens?

我正在测试使用 csurf 包和 express-session 包的 NodeJS express 应用程序。

问题

在测试时,我必须发出应包含 csrf token 的请求,但因为我不太了解 csurf 中间件如何在传入请求中验证 csrf tokens,即在测试应用程序时造成很多问题。

问题

谁能简单解释一下,当 csurf 中间件与 express-session 包一起使用时,csurf 中间件如何验证 csrf tokens?它在请求中收到令牌时如何验证令牌?令牌应该在 headers 中发送还是在请求中发送 body?是每次呈现新页面时都会创建新令牌,还是每个用户只有一次令牌session?

我还想知道在 cookie-parser 包中使用 csurf 中间件时,令牌验证过程会发生什么变化?

csurf 通过将令牌秘密存储到 session(在 express-session 的情况下)或直接存储到 cookie(在 cookie-parser 的情况下)中来工作。然后,服务器端应通过 req.csrfToken() 使用动态生成的(每个请求)令牌呈现网站。这个csrf token来源于token secret,后面可以验证。

调用 csurf 受保护的端点时,此令牌应由客户端通过 body 或 header 包含(参见默认值 here)。然后,中间件将从 session 或 cookie 中获取令牌秘密,然后验证它是由用户拥有的秘密生成的有效令牌。如果验证失败,会抛出csrf错误。

由于生成的 csrf 令牌对时间不敏感,对于单元测试,您实际上可以将相同的令牌密码硬编码到 session 或 cookie 中,调用 req.csrfToken() 一次以接收有效令牌,然后继续为每个测试重复使用相同的令牌。

是否针对每个请求或每个用户会话发布 CSRF 令牌似乎是一个有争议的领域,甚至 this Whosebug security question 上的前两个答案也不同意这个问题。

底线:

我们应该始终遵循 OWASP 的建议,其中指出 per request CSRF tokens are more secure, but not necessary and can cause other problems

CSRF tokens should be generated on the server-side. They can be generated once per user session or for each request. Per-request tokens are more secure than per-session tokens as the time range for an attacker to exploit the stolen tokens is minimal. However, this may result in usability concerns.

...

值得注意的是,后退按钮问题可能不是 csurf 的问题,因为它使用秘密机制来 generate/validate 令牌(允许旧令牌验证)。

最后,如果您要构建 SPA:

csurf 文档说 only send down the CSRF token once on the route that renders the page