我正在使用 React SPA、Express、Express-session、Passport 和 JWT。
我对存储 token 的一些不同客户端存储选项感到困惑:Cookies、Session 和 JWT/Passport。
token 是否必须存储在 cookie 中,即使我可以将它们存储在 req.sessionID
中?
许多网站使用 cookie 来存储购物车 token 。到目前为止,我已经根据 session ID 存储了购物车数据,而没有添加任何 cookie。
So when users visit my website, I will match it with their
req.sessionID
and then retrieve the data in the database like shopping carts and user session.
我需要存储cookies吗?我可以通过
req.sessionID
访问它以获取所需的数据。第二个
我已使用
passport-google-oauth20
进行身份验证.我成功登录后,数据被保存到 session 中。并将其发送给客户端,我必须通过 URL 查询 ?token='sdsaxas'
发送它.in this case I get a lot of difference of opinion. someone saved it into local storage and someone saved it into cookies by converting it to a token using JWT.
jwt.sign(
payload,
keys.jwt.secretOrPrivateKey,
{
expiresIn:keys.jwt.expiresIn // < i dont know what is this expired for cookies or localstorage ?
}, (err, token) => {
res.redirect(keys.origin.url + "?token=" + token);
});
我确实可以使用 sessionID(没有 cookie 或 localstorage)存储与 session 相关的所有内容吗?
由于我使用 React SPA,因此只能通过执行一次或每次页面刷新并检索数据然后保存到 redux 中。
最佳答案
这个答案基于无状态方法,因此它没有讨论传统的 session 管理
你问了两个完全不同的问题:
作为电子商务网站的用户,我希望我在上类途中从移动设备添加到购物车中的任何商品都应该在我回家后从 PC 登录网站时出现在购物车中。因此,购物车数据应保存在后端数据库中并链接到我的用户帐户。
在使用 OAuth 2.0 进行身份验证时,JWT 访问 token 和/或刷新 token 需要存储在客户端设备中的某个位置,以便一旦用户通过提供登录凭据对自己进行身份验证,他就不需要再次提供他的凭据浏览网站。在这种情况下,浏览器本地存储、 session 存储和 cookie 都是有效的选项。但是,请注意,此处的 cookie 未链接到服务器端的任何 session 。换句话说,cookie 不存储任何 session ID。 cookie 仅用作访问 token 的存储,访问 token 随每个 http 请求传递到服务器,然后服务器使用数字签名验证 token 以确保它没有被篡改和过期。
尽管访问和/或刷新 token 的所有三个存储选项都很流行,但如果以正确的方式使用,cookie 似乎是最安全的选项。
为了更好地理解这一点,我建议您阅读 this和 this以及 OAuth 2.0 规范。
2019 年 2 月 16 日更新
我之前说过 cookie 似乎是最安全的选项。我想在这里进一步澄清这一点。
我认为浏览器的原因
localStorage
和 sessionStorage
没有为存储 auth token 提供足够的安全性如下:localStorage
和 sessionStorage
不跨子域共享。因此,如果我们有两个 SPA 在不同的子域上运行,我们将无法获得 SSO 功能,因为组织内的另一个应用程序无法使用一个应用程序存储的 token 。有一些解决方案使用 iframe
,但这些看起来更像是变通方法而不是好的解决方案。而当响应头 X-Frame-Options
用于避免点击劫持攻击 iframe
, 任何带有 iframe
的解决方案毫无疑问。但是,可以通过使用指纹(如 OWASP JWT Cheat Sheet 中所述)来减轻这些风险,而指纹又需要一个 cookie。
指纹的想法是,生成加密强的随机字节串。然后原始字符串的 Base64 字符串将存储在
HttpOnly
中。 , Secure
, SameSite
带有名称前缀的 cookie __Secure-
.应根据业务需求使用域和路径属性的正确值。字符串的 SHA256 哈希值也将在 JWT 的声明中传递。因此,即使 XSS 攻击将 JWT 访问 token 发送到攻击者控制的远程服务器,它也无法发送 cookie 中的原始字符串,因此服务器可以基于 cookie 的缺失拒绝请求。 cookie 是 HttpOnly
XSS 脚本无法读取。因此,即使我们使用
localStorage
和 sessionStorage
,我们必须使用 cookie 来确保它的安全。最重要的是,我们添加了如上所述的子域限制。现在,使用 cookie 存储 JWT 的唯一问题是 CSRF 攻击。由于我们使用
SameSite
cookie,CSRF 得到缓解,因为跨站点请求(AJAX 或仅通过超链接)是不可能的。如果该网站在任何旧浏览器或其他不支持的不太流行的浏览器中使用 SameSite
cookie,我们仍然可以通过额外使用具有加密强随机值的 CSRF cookie 来缓解 CSRF,这样每个 AJAX 请求都会读取 cookie 值并将 cookie 值添加到自定义 HTTP header 中(除了不应该这样做的 GET 和 HEAD 请求)任何状态修改)。由于CSRF由于同源策略无法读取任何内容,并且它基于利用POST,PUT和DELETE等不安全的HTTP方法,因此该CSRF cookie将减轻CSRF风险。所有现代 SPA 框架都使用这种使用 CSRF cookie 的方法。提到了 Angular 方法 here .此外,由于 cookie 是
httpOnly
和 Secured
, XSS 脚本无法读取。因此,XSS 也得到了缓解。可能还值得一提的是,通过使用适当的
content-security-policy
可以进一步减轻 XSS 和脚本注入(inject)。响应头。其他CSRF缓解方法
httpOnly
曲奇饼。 关于javascript - 我是否必须将 token 存储在 cookie、localstorage 或 session 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54258233/