最近在使用 Token 做登录身份. 自己尝试了一些方案, 但是感觉都不完美, baidu/google 也都没有找到好方案. 所以提出来, 请各位指点下.
token 自动续订, 是为了保证用户在使用系统的过程中,自动刷新 accessToken,用户无感知,不会被要求强制登录.
请求响应 401 且 accesstoken 无效时,refreshToken retry.
为了防止并发, 前端需要双重判断加锁, 保证同时有多个请求时, 只会获得一个 AccessToken.
定时检查 token 有效期, 当 token 有效期低于阈值,且用户在最近一定时间内操作过页面, 就 refreshToken.
refreshToken 的临界点,可能会有并发的业务请求使用 旧的 accessToken, 导致请求失败. 所以在 refreshToken 时,不能立即删除旧的 accessToken,而是 10 秒后过期(删除).
后端使用 filter, 如果 accessToken 校验失败, 则使用 refreshToken 刷新 accessToken, 并 set-cookie.
refreshToken 的临界点,可能会有并发的业务请求. 如果 refreshToken 允许复用,会导致刷新出多个不同的 accessToken, 如果 refreshToken 不允许复用,会导致其他请求刷新 accessToken 失败.
为了解决这个问题, 需要在刷新 accessToken 时, 双重判断加锁. 保证同时有多个请求时, 只会生成一个 AccessToken.
该方案不符合 Oauth2 规范, refreshToken 应该是 client 行为.
由于用户需要在个人电脑与公共电脑上切换.为了保护账号安全,个人电脑上,希望有长期 Token, 公共电脑上,应该是短期 Token. 所以需要提供 RememberMe 特性. 我当前使用的方案如下:
另外还有一种方案:
有以下问题,各位有什么想法:
1
xjoker 2021-08-03 11:37:59 +08:00
等一个大佬来指导下 😄
最近做一个项目也遇到这种问题了 |
2
liuxianzhuo 2021-08-03 11:52:43 +08:00
我是用的第一种和第二种结合的方式
前端每次请求时在请求拦截器里判断当前 accesstoken 过期时间,当快过期或者已经过期时使用 refreshtoken 获取新的 accesstoken 并锁住新的并发请求,获取到 accesstoken 后解锁并使用新的 accesstoken 访问 |
3
darknoll 2021-08-03 12:52:04 +08:00
@liuxianzhuo 前端如何判断当前 accesstoken 过期时间?
|
4
cp19890714 OP @darknoll 我当前使用的是 spring security oauth2. 生成 accessToken 时, 会有过期时间 Date, 以及有效时长 Long.
|
5
liuxianzhuo 2021-08-03 14:08:27 +08:00
@darknoll 生成 accesstoken 时后端可以一并吧有效时长传到前端,后端没有传的话也可以手动 base64 解码 token,里面有个字段是过期时间
|
6
sparrww 2021-08-03 14:32:24 +08:00
用户量不大不用纠结,直接每次请求服务端 token 续期就行,想怎么控制怎么控制,量大了加配置,何必自己找麻烦。
|
7
777777 2021-08-03 15:22:45 +08:00
用户每请求一次接口,后端就把 token 过期时间重置为 7 天,当用户 7 天没有操作,token 过期,需要重新登录。
|
8
onhao 2021-08-03 15:38:07 +08:00
if (isset($_GET['renewal'])) {
$code = $_POST['code']; $uid = c2u($code); if ($uid) { $data['code'] = u2c($uid); $data['status'] = 0; } } |
9
cp19890714 OP |
10
sparrww 2021-08-03 16:43:34 +08:00
@cp19890714 你没理解我意思,你可以续期为四小时,也可以根据不同用户随时过期,服务端怎么操作设计,不是你说了算吗
|
11
coderwl 2021-08-04 11:07:43 +08:00
client 是相对 Oauth server 的,和前后端没关系吧。刷新 token 之前在我们项目里是用户请求的时候判断,如果快过期了,后端续期,返回的 header 里放新的 token,APP 端有对应的 header 处理逻辑,后端异步删除旧 token
|
12
zliea 2021-08-04 14:12:05 +08:00
1. 后端刷新的问题在于,前端每次都要 refresh token 进行传递,这样设计 refresh token 的意义在哪里?
2. 前端刷新统一一套规则,401 统一 redirect 到一个页面进行刷新,如果刷新成功跳转回之前页面,如果刷新失败,跳转登录页面 remeber me:不 remeber 的不返回 refreshtoken 即可,accesstoken 浏览器关闭失效,最长时间比如 2 个小时。 |