Anti-CSRF 令牌是存储在客户端、服务器端还是两者兼而有之?

Posted

技术标签:

【中文标题】Anti-CSRF 令牌是存储在客户端、服务器端还是两者兼而有之?【英文标题】:Are Anti-CSRF tokens stored on client-side, server-side, or both? 【发布时间】:2019-03-17 05:08:28 【问题描述】:

我正在创建一个带有 Node.js 后端的 React Js 网站。我一直在尝试找出一种用户身份验证实现来防止 CSRF 攻击,但是我真的很困惑在哪里存储 Anti-CSRF 令牌。

我对安全实现的思考过程如下...

    用户提交使用凭据登录的请求。 凭据已通过身份验证。 服务器创建会话。 服务器创建 JWT 以用作 Anti-CSRF 令牌。 服务器将 JWT(反 CSRF 令牌)存储在会话存储中。 服务器向客户端发送响应。 响应具有在客户端的 HttpOnly cookie 中存储会话 ID 的标头。 响应负载包括 JWT(反 CSRF 令牌)。 客户端收到响应。 HttpOnly cookie 保存会话 ID 存储在客户端。 客户端将 JWT(反 CSRF 令牌)存储在 localStorage 中。

我认为当用户需要请求信息时,客户端可以通过标头或有效负载发送 JWT(Anti-CSRF 令牌),由于它是 cookie,会话 ID 将自动发送。然后,服务器可以检查会话存储中是否存在 JWT(Anti-CSRF 令牌)。

我知道 JWT(反 CSRF 令牌)需要在某个时候刷新。

我的困惑是由于在客户端存储了 JWT(反 CSRF 令牌)。我一直在读它应该只存储在服务器上。但如果它只存储在服务器上,它似乎根本没有做任何事情。

我曾考虑同时使用 cookie 和 localStorage,因为似乎如果对服务器的请求需要 HttpOnly cookie 和 localStorage 中的某些内容来发回“授权”响应,则攻击者需要同时成功运行会话和成功实施 XSS 攻击以获取 Anti-CSRF 令牌。

我最近才开始学习 CSRF 和 XSS,所以我可能完全错了,我的实现中可能存在我遗漏的巨大缺陷。但我的主要问题是……反 CSRF 令牌不需要存储在客户端和服务器上吗?

【问题讨论】:

【参考方案1】:

它们也被称为“CSRF 令牌”。当客户端请求表单(例如银行登录页面)时,服务器生成令牌并将它们传递给客户端,当客户端填写表单时,客户端将 CSRF 令牌与完成的表单一起传递。服务器验证令牌值,如果匹配,则满足请求。 CSRF 令牌以同步器令牌模式存储在服务器端。

【讨论】:

以上是关于Anti-CSRF 令牌是存储在客户端、服务器端还是两者兼而有之?的主要内容,如果未能解决你的问题,请参考以下文章

将令牌从服务器传递到客户端并以安全方式存储

Oauth2令牌 - 我可以将令牌存储在会话中

存储 JWT 令牌

如何防止刷新被盗的访问令牌

Node Express - 身份验证令牌的存储和检索

在服务器上存储我自己的访问令牌/秘密的正确方法