V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
MingLovesLife
V2EX  ›  程序员

不懂就问,请教一下前端无感刷新 token 到底有没有意义?

  •  
  •   MingLovesLife · 2 天前 · 5984 次点击
    在技术网站看到过无数次前端无感刷新 token 的文章,一直很费解,为啥要刷新 token 呢?那前端给 token 刷新了,token 还有啥意义呢?

    文章给出的原因是,用户正操作着呢,token 突然过期,跳登录页用户体验不好。

    实现步骤:
    accessToken 简称 at ,refreshToken 简称 rt
    1. rt 有效期长,at 有效期短
    2. at 过期了拿 rt 换 at ,重新请求

    疑问:
    1. 既然 rt 长期有效,直接用 rt 有啥问题
    2. 如果从安全考虑,rt 被抓包拿了,也没辙呀
    3. 既然后端知道用户操作了,如果是非异常操作,就自动给 token 延时行不?

    不知道该方案具体是为了什么,还请大神们赐教。希望接到类似需求老哥们聊聊

    PS:轻喷,心平气和
    第 1 条附言  ·  1 天前
    感觉大家的解答,目前出现了两个能说服我的理由(也是自己总结,不知对错,可以修正)
    1. rt 无法访问资源服务器,at 无法访问用户服务器,给抓包、攻击提高了复杂度
    2. 资源服务器可以直接解析 at ,仅在 at 过期后才访问用户服务器,缓解了用户服务器的压力

    产生了新的疑问:
    有几位提到了 at 不可修改,所以一般有效期设置的较短,那么
    1. 当用户修改了账号密码时,会主动通知资源服务器 at 过期了吗?
    2. 我不知道 1 的答案,所以先假设不通知,那该怎么办呢?
    67 条回复    2025-01-07 16:23:12 +08:00
    qhd1988
        1
    qhd1988  
       2 天前
    我觉得只是增加抓包难度罢了,提升用户体验只是带来的"副作用",
    安全不安全,主要看你项目有没有真金白银的价值,有的话,管你啥 refresh_token 还是啥,分分钟给你抓出来
    neptuno
        2
    neptuno  
       2 天前   ❤️ 3
    这么一说确实有道理的,小厂反正无所谓怎么搞都行。大厂的话我的理解就是 refreshToken 可以多一道控制,accessToken 签出之后无法控制失效(除非加黑名单),但 refreshToken 可以控制下一次 accessToken
    wzj92712
        3
    wzj92712  
       2 天前
    这一切的前提是 HTTPS.
    如果有 HTTPS.可以保证你只会被重放攻击.不会真正泄漏 token 的值.

    1.小项目这样做没问题. 只不过如果 rt 可以请求资源. 那就是说可能会被一直重放攻击. 如果 rt 只能换 at.at 过期了.他就不能重放了(他得再次抓包). 安全一丢丢.
    2.基于前提.rt 不会被获取值的.
    3.可行但怪麻烦的,不如直接用长期 token

    个人的理解.不一定完全正确.
    lidashuang
        4
    lidashuang  
       2 天前
    refreshToken 不能访问资源啊
    lidashuang
        5
    lidashuang  
       2 天前
    accessToken 有效期短一点,相对安全一点
    jifengg
        6
    jifengg  
       2 天前
    我以前碰到的时候思考的,不一定对:“服务器端校验 refreshtoken 消耗的资源比 accesstoken 大。”
    更深的原因就没有细究了。
    635925926
        7
    635925926  
       2 天前
    我也无法理解为啥要 jwt ,短短的 token 不香吗
    unlimitedsola
        8
    unlimitedsola  
       2 天前   ❤️ 1
    Access Token 可能是 JWT, 服务端收到时可以通过校验签名来确认是否有效, 不一定需要查询数据库或做完整的校验. JWT 弊端是签出后无法轻松控制失效, 所以需要 Refresh Token 来弥补.
    firstmetcs
        9
    firstmetcs  
       2 天前   ❤️ 1
    我理解的每个请求都有 access_token 的传递,但是只有登录、刷新 token 等操作才会传递 refresh_token ,这样的话 refresh_token 被抓包的几率小多了,然后 access_token 泄露的话那么下次过期自然被抓包的那次就不能再使用了
    ScepterZ
        10
    ScepterZ  
       2 天前   ❤️ 1
    2 、rt 一般会存数据库,所以有办法踢,at 可以接受不能踢,有效期可以很短
    InkStone
        11
    InkStone  
       2 天前   ❤️ 1
    @wzj92712 https 不能重发的。高版本 tls 如果没对握手信息做记录,会话结束后,你拿着私钥都没法把流量解密。更不要说重放了。
    这种我理解更多还是防 XSS 。
    maichael
        12
    maichael  
       2 天前
    1. refreshToken 不应该能访问资源服务器,简单来说 RT 和 AT 访问的“服务器”都是不一样的。
    2. 这是防中间人的问题,跟是否使用 RT&AT 方案无关,这是 HTTPS 等方案的事。
    3. 不行,跟 1 同理,AT 和 RT 是访问不同服务器的钥匙,你有 AT 不代表你有 RT ;抛开权限不同这点,如果后端实现了自动刷新,那就相当于 AT 和 RT 合一,又回到了单一 token 的方案了。

    延伸谈一下,AT&RT 与单 Token 的方案最大的区别是把“获取授权”跟“获取资源”两个行为彻底分离,前者是一个高危害低频率的行为,后者是一个低危害高频率的行为(这里的危害是指 Token 泄漏后带来的影响);越高频率就意味着越高的暴露风险,所以对于高危害的行为,单独出来放在一个低出现频率的 Token 能提高安全性。
    ttimasdf
        13
    ttimasdf  
       2 天前
    不负责任的盲猜一下,没有开发经验纯盲猜啊

    弄个有效期短的临时 ak ,对热缓存和集群部署更友好,token 表直接放内存里面弄个 kv cache 查,肯定比每次请求查用户表去校验 ak ,性能更高一点,只有 refresh token 换 ak 的时候,才需要查一下用户表,验证一下 refresh token 是否有效。
    lambdaq
        14
    lambdaq  
       2 天前
    放弃 jwt 直接全部服务器存状态吧。
    follower
        15
    follower  
       2 天前
    这玩意是用来单点登录的
    双 token 方案既减轻了服务器压力,又对用户的登录态具有一定的控制,其实是个折中的方案
    cat
        16
    cat  
       2 天前   ❤️ 1
    @maichael 换句话说,就是用 RT 代替了账号密码,如果每次请求都携带账号密码,则暴露的风险更高
    johnnyNg
        17
    johnnyNg  
       2 天前
    看看腾讯云,token 过期,直接弹窗登录就好了,不用跳到登录页面
    SilentRhythm
        18
    SilentRhythm  
       2 天前
    at:一般是 jwt ,无状态服务颁发后后端无法控制,而且承载实际权限,所以为了安全,设计有效时间一般较短
    rt:at 有效期短势必需要刷新了,那么刷新 ak 有哪些方案可选?:
    1. at 刷新 at:那我还不如直接长有效时间 at ,安全考虑,不成立;
    2. username/password 刷新 at:username/password 手动输入体验就差,存放在 local-stroage 又太危险了;
    3. rt:折中方案
    myderr
        19
    myderr  
       2 天前
    这个是一个折中方案,jwt 是无状态的嘛,如果签了一个很长的 at,那么这个用户就无法控制( ban )了。但是有个 rt ,那么类似于多久让前端主动请求一下用户状态。
    purringpal
        20
    purringpal  
       2 天前 via iPhone
    增加操作空间吧,如果后端什么监控和防护措施都没有,那就是脱裤子放屁,去你所说 rt 被抓包了等于密码泄露。但是如果加了防护措施可以规避异常访问,用的来说就是在用户体验与安全性的折中做法。。
    purringpal
        21
    purringpal  
       2 天前 via iPhone
    @purringpal 错别字: 如你所说、总的来说
    xiangyuecn
        22
    xiangyuecn  
       2 天前
    以前应该很香,现在看应该算是裹脚布 又长又臭
    w4n9hu1
        23
    w4n9hu1  
       2 天前
    这是为了缓解 OAuth2 在实际应用中的一个主要缺陷,通常访问令牌一旦发放,除非超过了令牌中的有效期,否则很难(需要付出较大代价)有其他方式让它失效,所以访问令牌的时效性一般设计的比较短,譬如几个小时,如果还需要继续用,那就定期用刷新令牌去更新,授权服务器就可以在更新过程中决定是否还要继续给予授权。 -- 凤凰架构
    XCFOX
        24
    XCFOX  
       2 天前   ❤️ 17
    accessToken 、refreshToken 双 Token 只在分布式|微服务架构下有意义。

    考虑我们有用户微服务和订单微服务,我们把用户信息存储在用户微服务,向订单微服务发起请求时需要验证用户有效性:
    1. 如果使用单 token 方案,订单微服务接到请求时 需要向用户微服务发起询问来验证用户有效性,在这一步至少需要一次网络通信。
    2. 如果使用双 token 方案,向用户微服务发起请求时携带 refreshToken ,向订单微服务发起请求时携带 accessToken ,accessToken 过期时向用户微服务发起请求重写签发 accessToken 。
    accessToken 具有以下特性:
    · 明文:这允许订单微服务直接从 accessToken 读取用户信息而不必询问用户微服务;
    · 具备签名:这允许订单微服务直接验证 accessToken 的有效性而不必询问用户微服务;
    · 不可篡改:这使得 accessToken 一经用户微服务签发则在有效期内一直有效,当用户更改密码或其他需要重制登录状态的时候 accessToken 也不受影响,为了满足重制登录状态的需求 accessToken 的有效期一般比较短。
    总结一下,双 token 方案使得订单微服务微服务不用向用户微服务发起询问,代价是 accessToken 不可篡改、登录状态难以清除。

    回答楼主的问题:
    1. refreshToken 只能向用户微服务发起请求,订单微服务无法验证 refreshToken 的有效性;

    2. 是的;

    3. accessToken 不可篡改,不可延时;

    个人看法:双 token 方案带来的「无需向认证服务询问」的特性有一点点优势;但很多场景会有下「踢出用户」的需求,这时候使用双 token 要么等着 accessToken 过期,要么向认证服务发起询问,前者实时性低,后者让损失了 双 token 方案唯一的优势。我的建议是摒弃双 token 方案,使用单 token 存 redis ,认证服务和业务服务都直接从 redis 读取用户状态。
    wu67
        25
    wu67  
       2 天前
    讲真, 我觉得还不如那个脱裤子放屁的操作: 加一道 redis 检验, 判断应该 401 还是正常使用, 既使用了 jwt 的简单粗暴, 又成功把部分数据库压力转移到内存去.
    coderlxm
        26
    coderlxm  
       2 天前 via Android
    这个话题展开讲的话内容太多了,简单说就是一切还是要回归到你的业务需求上,rt 存在本身肯定是有意义的
    jonsmith
        27
    jonsmith  
       1 天前
    安全性考虑,在 JWT 场景,at 有效期不能太久,因为无法踢掉。rt 重新签发,能做一些安全校验。
    sikuu2al
        28
    sikuu2al  
       1 天前
    去年实习的时候有在掘金提过类似的问题,也是关于双 token 的意义的。实习公司做的小项目也要上双 token ,到现在仍旧没有一个能够彻底说服我的理由。
    keakon
        29
    keakon  
       1 天前
    类 JWT 场景下,at 是用签名来验证,而不用实际比对数据库。当发生某些需要 revoke token 的场景时,如果 at 的有效期足够短,可以不实现。等到过期校验 rt 时,发现不可用了,再进行退出。
    sampeng
        30
    sampeng  
       1 天前
    所有用无限期的 token 的时候都一定有过临时 token 。比如后台某个服务/脚本临时用个 token 。。然后时间长了,这个 token 就无法改了,特别的蛋疼。token 就应该是无状态的,一定时间内轮换。不然请用 cookie/session 机制。
    sampeng
        31
    sampeng  
       1 天前
    另一方面。我就在我之前公司 app 上碰到过。无聊的黑客,登陆了就拿着 token 无限制的做任何事。等你发现的时候已经受损失了。如果是双 token 机制,上线的时候就会把访问频率考虑进去。单 token 的,大部分程序员应该实现的就是又不是不能用策略。。防刷?想啥呢。。。
    shenyuzhi
        32
    shenyuzhi  
       1 天前 via iPhone
    纯粹就是为了性能,和安全性/分布式什么的一点关系都没有。
    at 是离线校验,不读数据库。
    rt 是在线校验,需要访问数据库。
    假设某种业务每个小时访问接口 1000 次,at 有效期 1 个小时。此时每个小时可以省 999 次访问数据库。只有过期的那次才需要刷一下
    SilentRhythm
        33
    SilentRhythm  
       1 天前
    针对新的疑问:
    1. 不通知;
    2. 只能等待过期,所以才设计较短的有效期来一定程度上规避安全风险。
    ilylx2008
        34
    ilylx2008  
       1 天前
    看到一个银行的实现,accessToken 有效期 2 分钟
    GooMS
        35
    GooMS  
       1 天前
    小业务规模上,直接签一年的
    crysislinux
        36
    crysislinux  
       1 天前 via Android   ❤️ 1
    refreshToken 我的看法是只是给 jwt 打个补丁,jwt 这东西它就不适合用来做用户登录。用户登录还是老老实实用 session 吧。
    Nazz
        37
    Nazz  
       1 天前 via Android
    鉴权方案有很多种,JWT 属于很辣鸡的那类。云厂商喜欢用 api_key 标识账户,api_secret 对参数签名,生成一次性的 token
    Jtyczc
        38
    Jtyczc  
       1 天前 via Android
    acessToken 用来感知用户是否在线
    SenLief
        39
    SenLief  
       1 天前
    jwt 只是鉴权方案的一种形式,也不一定要用。
    tairan2006
        40
    tairan2006  
       1 天前 via Android
    无意义,直接用服务端 token ,jwt 只适合一次性授权
    webcape233
        41
    webcape233  
       1 天前 via iPhone
    tls + cookie 不香吗
    ArianX
        42
    ArianX  
       1 天前
    refreshToken ,认证应该可以结合一些签名、特征校验吧,比如 refreshToken 只在一台设备、一个地址生效?
    wangtian2020
        43
    wangtian2020  
       1 天前
    为了假装自己的系统很有价值会被人挟持 token
    accelerator1
        44
    accelerator1  
       1 天前
    这种双 token 对应的基本是 oauth2.0 ,查一下 oauth2.0 中对于这两个 token 的定义就明白了。

    使用双 token 主要是为了防止 token 泄漏导致的安全问题。at 泄漏,一般两小时就过期了,风险可控; rt 泄漏,过期时间很长,所以一般不会频繁使用。

    前端使用双 token ,主要的泄漏途径就是网络传输层面,被抓包了很容易拿到你的 token ,所以使用 at 减少风险;至于 xss ,目前主流的认证方式都没啥用。。。

    当然,国内的认证服务基本不是完全基于 jwt ,都是有状态的,吊销 at 、rt 很容易,这样的场景下,是不是双 token 没啥区别了。
    flytsuki
        45
    flytsuki  
       1 天前
    我们小公司直接 token 存 redis,方便登录后踢掉上一个登录状态
    accelerator1
        46
    accelerator1  
       1 天前
    @webcape233 不香,现在浏览器基本默认禁止跨域携带 cookie 了,做页面嵌套基本会死,特别是内网环境没有固定域名的情况下。
    aloxaf
        47
    aloxaf  
       1 天前
    最能说服我的理由是——你不信任使用 at 的客户端。

    比如第三方提供的集成服务,我不希望它能拿到有效期很长的 at 。短 at + 长 rt 就能确保用户不使用服务后它能迅速失去对用户资料的访问权。
    samnya
        48
    samnya  
       1 天前 via iPhone   ❤️ 4
    根据 accessToken 能被泄漏的理论,我觉得他既然能抓取到 token ,也能够直接篡改返回值。
    那么直接把用户的响应改成 401 ,客户端就会立刻触发刷新 token 流程,此时就获得了 refreshToken
    2han9wen71an
        49
    2han9wen71an  
       1 天前
    我们公司的 rt 和浏览器指纹还有用户 Ip 绑定,不一致就失效。
    另外 at 的用途:
    1. 用户及时下线,at 一般是 15 分钟,rt 是一个星期
    2. 减少用户访问 rt 的次数,一般 rt 放数据库做鉴权,实际上就是账号加密码
    canvascat
        50
    canvascat  
       1 天前
    之前加了双 token ,去年又去掉了
    clocean
        51
    clocean  
       1 天前
    斗鱼直播是不是使用了这个技术?反正作为用户来说,体验无敌,登录一次之后就没登录过了
    telemsg
        52
    telemsg  
       1 天前
    1. 既然 rt 长期有效,直接用 rt 有啥问题
    2. 如果从安全考虑,rt 被抓包拿了,也没辙呀
    3. 既然后端知道用户操作了,如果是非异常操作,就自动给 token 延时行不?

    1 ) rt 过期了咋办? 重新登陆微信? rt+at 能灵活控制过期时间 ( rt 还能 revoke )
    2 )对。 什么技术抓包也没有办法。 尽量 https
    3) 自动延时? 什么情况触发? 我开发业务还需要关心? 你们在网关配置好,我业务开发可不管 (分离)
    abc1310054026
        53
    abc1310054026  
       1 天前
    @accelerator1 过滤掉跨域的 cookie 是正确的。当然你可以设置 cookie 跨域共享。
    telemsg
        54
    telemsg  
       1 天前
    产生了新的疑问:
    有几位提到了 at 不可修改,所以一般有效期设置的较短,那么
    1. 当用户修改了账号密码时,会主动通知资源服务器 at 过期了吗?
    2. 我不知道 1 的答案,所以先假设不通知,那该怎么办呢?

    1 )通知了也没有用,at 就是无状态的,所以尽量是配置较短的时间
    这里延伸出另一个问题: 如何做单点退出? (简单来说就是要清理 client token, at 本身还是有效的)
    leokun
        55
    leokun  
       1 天前
    听了大家的回答,我认为 accessToken 是给 refreshToken 打补丁的
    refreshToken 每次都会访问用户数据库,accessToken 不需要。
    所以 accessToken 本质上是 refreshToken 的离线存储,保证一段时间内不需要再次访问数据库
    leokun
        56
    leokun  
       1 天前
    @leokun 前面提到 refreshToken 是给 accessToken 打补丁,我觉得说反了
    cat
        57
    cat  
       1 天前   ❤️ 1
    @samnya 卧槽牛逼!新思路!
    635925926
        58
    635925926  
       1 天前
    @shenyuzhi 现在单 token 基本存 redis ,也不存在什么性能问题啊
    635925926
        59
    635925926  
       1 天前
    @samnya 直接抓 rt ,在 pre-post 中每次获取最新 at 不是更爽
    byte10
        60
    byte10  
       1 天前
    回答其中一点,JWT 是无状态的,去中心化,无法踢出。所有很多大聪明就会加一个 redis 存起来,来判断是否过期 就扔掉,也就是说单纯脱裤子放屁。
    Alliot
        61
    Alliot  
       1 天前
    accessToken 用来真正的访问资源, 它通常是无状态的 JWT , 带有时间戳,过期时间短。

    refreshToken 一般在服务端有存(方便吊销),过期时间长

    这样的好处是,用户的访问直接使用 accessToken, 这样不会每次都需要访问服务端鉴权,可以降低服务端压力。


    比如 accessToekn 30s 过期,那鉴权部分就从每次请求都鉴权-> 变成了 30s 才访问一次鉴权续期

    降低了服务端压力
    zorui
        62
    zorui  
       1 天前
    @635925926 使用 jwt 服务端不需要存储, 只需要算法验证, 短短的 token ,要么服务端存储,要么搞一套新的算法规则 还不如 jwt 呢。jwt 最大优势就是只需要算法验证验证就行。
    dogfeet
        63
    dogfeet  
       1 天前
    对于我们这种游戏业务,只允许单客户端登录的,有很重要的意义。

    1. rt 的存在,就是为了减少核心认证数据的传输频率(比如账号密码,手机验证码等)
    2. rt 会持久化,at 的校验成本更低,往往会存在内存中直接校验。
    3. rt 无法用来登录,只能用来刷新 at ,重点是一个账户只有唯一的一个有效 rt ,每次刷新都需要当前正确的 rt ,刷新后 rt 会变,之前的 rt 就失效了。如果所谓的 rt 被抓包拿了,除非只有你一个人用,否则,用户刷新失败触发账号密码或验证码登录,此时刷新的 rt 会覆盖掉抓包拿的 rt 。也就是游戏中的发现自己被挤下来后,自己用最高优先级的账号密码登录,对方就无法再登录了。

    重点:
    rt 只能使用一次,这是与账户密码最大的不同点。
    rt 只能使用一次,这也是与 at 最大的不同点,成本较 at 高。

    总结:
    正常用户的使用过程中,几乎很少触发账户密码验证码登录,体验更好。
    非正常使用过程中,也能一定程度的保证安全。
    减少账户密码的传输频率也能降低其被窃取的风险。
    635925926
        64
    635925926  
       1 天前
    @zorui jwt 无状态,不储存,无法被控制。反而是缺陷。
    sardina
        65
    sardina  
       1 天前
    你说的这种不用 rt 直接把 at 刷新也可以实现无感刷新这种双 token 主要还是用在 oauth2 里,第三方应用申请一个 rt ,然后用 rt 去申请 at ,at 有过期时间,过期了用 rt 去重新获取
    这里有一篇文章可以学习学习 https://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
    meteora0tkvo
        66
    meteora0tkvo  
       1 天前
    单纯是后端懒得写自动延长 token 有效期的业务,所以交给前端来调取憋屈的“刷新 token”接口
    dengkj
        67
    dengkj  
       1 天前
    设计两个 token 主要是为了平衡安全性和便利性。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5239 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 09:33 · PVG 17:33 · LAX 01:33 · JFK 04:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.