【发布时间】:2022-01-13 19:23:17
【问题描述】:
我有一个使用 node 和 TypeScript 开发的 API 和 Web 客户端。用户可以使用 JWT 进行身份验证。该系统可以正常工作,但我想知道它是否安全,或者它是否有缺陷:
系统如下:
-
客户端 POST 到 API 上的 /login 端点
-
在 API 上,当收到 POST /login 请求时,会生成一个 JWT 令牌,使用一些用户数据作为内容,以及一个存储为环境变量的秘密字符串:
// SECRET is an environment variable == "bd0b2760-5869-11ec-bf63-0242ac130002" const userData = { id: 1, name: "John Doe", }; const token = jwt.sign(JSON.stringify(userData), SECRET); -
在 POST /login API 的响应中发送两个 cookie:一个持有令牌,另一个包含原始用户数据:
return res .cookie('sessionData', userData, { httpOnly: true, path: '/', domain: "example.com", }) .cookie('sessionToken', token, { httpOnly: true, path: '/', domain: "example.com", }).send(); -
客户端收到令牌。客户端可以确定
sessionToken是有效的,因为它是由API 发送的。它不会验证它,因为它需要 SECRET,我们不想将它暴露给客户端。 -
重新加载时,客户端将使用
sessionDatacookie 知道用户已登录,并使用此数据加载客户端用户数据。 -
由于这些 cookie 是 http cookie,因此这两个 cookie 都附加到发送到 API 的每个请求中,并由 API 接收。对于需要身份验证的端点的每个请求,API 将解密
sessionToken并将其与sessionTokencookie 进行匹配:如果它们不匹配,API 将删除响应中的 cookie,从而有效地注销客户端。// SECRET is an environment variable == "bd0b2760-5869-11ec-bf63-0242ac130002" const sessionToken = req.cookies.sessionToken; const sessionData = req.cookies.sessionData; const decodedToken = jwt.verify(sessionToken, SECRET); if(decodedToken.id !== sessionData.id || decodedToken.name !== sessionData.name ) { return res .clearCookie('sessionToken', { path: '/', domain: "example.com" }) .clearCookie('sessionData', { path: '/', domain: "example.com" }) }
如前所述,该系统有效,而且看起来很安全。但也许我错过了一些东西,所以最好问一下。所有代码都是伪代码。
欢迎任何帮助!
【问题讨论】:
-
它是安全的,但安全程度取决于您的用户。如果用户登录并离开他们的终端,那么有人可能会获取他们的
sessionToken并恶意使用它。 cookie 在此基础上增加了一定程度的安全性,但不是防弹的。我会推荐一个超时系统,如果用户闲置 X 时间,则将其注销。这完全取决于您的信息的敏感程度以及您所寻求的安全级别。 -
非常感谢@CraigHowell。实际上我已经介绍了这个案例,我的 cookie 会在 48 小时后过期。虽然没有在示例中显示它
-
另外,由于它们是 httpCookies,我认为不可能使用 cookie 数据发送请求,因为只允许来自特定服务器的 cookie
标签: node.js express authentication jwt