我同意乔的回答
一种可能的解决方案是在您的数据库中添加一个设备标识字段并为每个设备发出一个刷新令牌。
但我想添加一些实现细节。
IMO 最强大和功能最强大的解决方案是:每个用户在数据库中有许多记录,每个记录有两列:refresh_token 和 device_id。
让我们检查主要情况:
- 用户登录。当然,他是在密码的帮助下做到的。他传递了 device_id (实际上是任何唯一的数字)。如果密码正确,服务器生成新的访问和刷新令牌,将 access_token 发送给客户端,并将 refresh_token 和 device_id 插入数据库。
- 用户消费服务. 他发送 access_token(女巫内部必须对用户信息进行编码,显然(例如他的登录名)和到期日期)。服务器检查令牌(在其秘密签名密钥的帮助下)以确保该令牌是真实的而不是假的。服务器还检查 access_token 到期日期。如果过期,用户必须在适当的 refresh_token 和(重要的!)device_id 的帮助下刷新它。如果数据库中的 refresh_token 不等于用户的令牌,那么我们就会被黑客入侵。但不要惊慌——我们只是删除刷新令牌并将用户重定向到登录页面!就是这样,只要 access_token 还活着,黑客就可以访问(像往常一样短时间)!如果您需要即时访问阻止,您可以将 access_token 与 refresh_token 一起存储在 db 中,并且还有一个内存中的 access_tokens 黑名单。
- 用户注销。他从 cookie/localstorage 中删除了他的 access_token,将 refresh_token 和 device_id 发送到服务器,服务器将它们从列表中删除。(我们不想收集过时的未使用令牌)
- 用户更改密码。服务器删除所有以前的 refresh_tokens。如果您使用令牌黑名单 - 将所有当前用户的 access_tokens 添加到其中。有了这样的解决方案,实现“从所有设备注销”功能也很容易。
- 黑客窃取 access_token 并且用户不知道它。黑客只能使用它直到它过期(短时间框架)。
- 黑客还窃取了 refresh_token 并制作了 refresh。用户将无法使用他的旧 refresh_token,在这种情况下他会提示再次登录,新的刷新和访问令牌将生成,黑客失去访问权限。(见案例#2)
您应该清楚了解的一件事:刷新令牌只能在黑客窃取访问/刷新令牌而不是真实密码的情况下拯救您!因为如果他得到了通行证,那么你就有麻烦了,你必须实现恢复密码的协议(例如,借助电子邮件或短信)
PS 拥有可以过期的 refresh_token 是个好主意。为防止出现这种情况,当jacker 从旧设备窃取访问权和刷新令牌时,该设备现在从未使用过。
PPS 最好有定期的数据库任务来清理过期的 refresh_token 行(也许你必须为此添加列 refresh_token_expiration_date)
PPPS 我不是安全专家,所以如果您认为有更好的解决方案,我很乐意进行讨论。
感谢阅读,希望对你有帮助)