Token 的自动续订,过期时间,常用设备登录的方案 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
cp19890714
V2EX    程序员

Token 的自动续订,过期时间,常用设备登录的方案

  cp19890714 2021-08-03 10:43:13 +08:00 4075 次点击
这是一个创建于 1575 天前的主题,其中的信息可能已经有所发展或是发生改变。

最近在使用 Token 做登录身份. 自己尝试了一些方案, 但是感觉都不完美, baidu/google 也都没有找到好方案. 所以提出来, 请各位指点下.

token 自动续订

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 行为.

RememberMe

由于用户需要在个人电脑与公共电脑上切换.为了保护账号安全,个人电脑上,希望有长期 Token, 公共电脑上,应该是短期 Token. 所以需要提供 RememberMe 特性. 我当前使用的方案如下:

  • 如果用户登录时,没有勾选 RememberMe, 则依赖 RefreshToken 的有效性自动续订.
  • 用户登录时,勾选了 RememberMe,则生成 RememberToken,有效期 14 天, 即使 RefreshToken 失效,也可以依靠 RememberToken 进行自动登录.

另外还有一种方案:

  • 如果用户登录时,没有勾选 RememberMe, 则 clientId = web-common, accessToken 有效期 1 小时, RefreshToken 有效期 2 小时.
  • 用户登录时,勾选了 RememberMe,则 clientId = web-remember, accessToken 有效期 24 小时, RefreshToken 有效期 14 天.

问题

有以下问题,各位有什么想法:

  • token 自动续订 和 RememberMe, 是否有其他方案?
  • token 的有效期多久合适? 我看到 github 的有效期是 14 天.
  • google/facebook/github 等公司是如何管理管理 token 的
12 条回复    2021-08-04 14:12:05 +08:00
xjoker
    1
xjoker  
   2021-08-03 11:37:59 +08:00
等一个大佬来指导下
最近做一个项目也遇到这种问题了
liuxianzhuo
    2
liuxianzhuo  
   2021-08-03 11:52:43 +08:00
我是用的第一种和第二种结合的方式
前端每次请求时在请求拦截器里判断当前 accesstoken 过期时间,当快过期或者已经过期时使用 refreshtoken 获取新的 accesstoken 并锁住新的并发请求,获取到 accesstoken 后解锁并使用新的 accesstoken 访问
darknoll
    3
darknoll  
   2021-08-03 12:52:04 +08:00
@liuxianzhuo 前端如何判断当前 accesstoken 过期时间?
cp19890714
    4
cp19890714  
OP
   2021-08-03 13:19:14 +08:00
@darknoll 我当前使用的是 spring security oauth2. 生成 accessToken 时, 会有过期时间 Date, 以及有效时长 Long.
liuxianzhuo
    5
liuxianzhuo  
   2021-08-03 14:08:27 +08:00
@darknoll 生成 acesstoken 时后端可以一并吧有效时长传到前端,后端没有传的话也可以手动 base64 解码 token,里面有个字段是过期时间
sparrww
    6
sparrww  
   2021-08-03 14:32:24 +08:00
用户量不大不用纠结,直接每次请求服务端 token 续期就行,想怎么控制怎么控制,量大了加配置,何必自己找麻烦。
777777
    7
777777  
   2021-08-03 15:22:45 +08:00
用户每请求一次接口,后端就把 token 过期时间重置为 7 天,当用户 7 天没有操作,token 过期,需要重新登录。
onhao
    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;

}
}
cp19890714
    9
cp19890714  
OP
   2021-08-03 15:51:44 +08:00
@sparrww
@777777 每次请求都为 token 续期, 有两个问题:
1. 如果 token 有效时间较短, 如 4 小时, 那么用户需要经常登录.
2. 如果 token 有效时间较长, 如 14 天, 会导致 token 长期不变, 影响安全.
sparrww
    10
sparrww  
   2021-08-03 16:43:34 +08:00
@cp19890714 你没理解我意思,你可以续期为四小时,也可以根据不同用户随时过期,服务端怎么操作设计,不是你说了算吗
coderwl
    11
coderwl  
   2021-08-04 11:07:43 +08:00
client 是相对 Oauth server 的,和前后端没关系吧。刷新 token 之前在我们项目里是用户请求的时候判断,如果快过期了,后端续期,返回的 header 里放新的 token,APP 端有对应的 header 处理逻辑,后端异步删除旧 token
zliea
    12
zliea  
   2021-08-04 14:12:05 +08:00
1. 后端刷新的问题在于,前端每次都要 refresh token 进行传递,这样设计 refresh token 的意义在哪里?
2. 前端刷新统一一套规则,401 统一 redirect 到一个页面进行刷新,如果刷新成功跳转回之前页面,如果刷新失败,跳转登录页面
remeber me:不 remeber 的不返回 refreshtoken 即可,accesstoken 浏览器关闭失效,最长时间比如 2 个小时。
关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3886 人在线   最高记录 6679       Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 22ms UTC 00:17 PVG 08:17 LAX 16:17 JFK 19:17
Do have faith in what you're doing.
ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86