高并发系统实战课
徐长龙
前微博架构师、极客时间架构师
11663 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 30 讲
结束语&结课测试 (2讲)
高并发系统实战课
15
15
1.0x
00:00/00:00
登录|注册

03|Token:如何降低用户身份鉴权的流量压力?

如果还有五分钟token要过期,重新发放token
access_token用于保存用户信息和权限信息,每隔15分钟更换一次
refresh_token用于更换access_token,有效期30天
验证token是否过期、是否合法通过签名验证
包含Header、Payload、Signature
提高截取客户端token并伪造用户身份的难度
包含过期时间,快过期的token会在客户端自动和服务端通讯更换
服务端解开token获取用户信息,无需和用户中心做交互请求
每次请求带上token
用户信息放到加密签名的token中
Web用户的token保存在cookie中时,建议加上httponly、SameSite=Strict限制
限制token的更换次数,定期刷新token
通讯过程必须使用HTTPS协议
JWT对离线App端十分友好,App可以将token保存在本地
用户中心检测更换token
双token方式
缺点:用户被拉黑后,客户端需在token过期后才能退出登录
优点:用户中心压力最大的接口可以下线,业务服务端解析请求带来的token即可获取用户信息
Token解密
Token生成
JWT(JSON Web Token)登录流程
问题:大流量下不稳定,维护的Session Cache空间大,缓存故障导致无法确认用户身份
优点:信息在服务端储存,对客户端不暴露敏感数据,每个登录用户有共享的缓存空间
每次请求带上session_id
用户信息写入服务端的Session缓存
设计简化系统压力的技巧,如文件crc32校验签名、Bloom Filter等,可以提高系统的工作效率,减少系统的交互压力
定期更换token,用户中心拥有一定的用户控制能力,也加大了破解难度
采用信任“签名”的token,把用户信息加密发放到客户端,让客户端本地拥有这些信息,解决用户中心的流量性能瓶颈
传统的Session方式会导致用户中心的流量很大,所有业务都很依赖用户中心
用户如果更换了昵称,如何快速更换token中保存的用户昵称呢?
安全建议
Token的更换和离线
JWT登录和token校验
Session方式实现登录用户的用户鉴权
文章总结
思考题
Token算法降低用户身份鉴权流量压力

该思维导图由 AI 生成,仅供参考

你好,我是徐长龙,这节课我们来看看如何用 token 算法降低用户中心的身份鉴权流量压力。
很多网站初期通常会用 Session 方式实现登录用户的用户鉴权,也就是在用户登录成功后,将这个用户的具体信息写在服务端的 Session 缓存中,并分配一个 session_id 保存在用户的 Cookie 中。该用户的每次请求时候都会带上这个 ID,通过 ID 可以获取到登录时写入服务端 Session 缓存中的记录。
流程图如下所示:
Session Cache实现的用户鉴权
这种方式的好处在于信息都在服务端储存,对客户端不暴露任何用户敏感的数据信息,并且每个登录用户都有共享的缓存空间(Session Cache)。
但是随着流量的增长,这个设计也暴露出很大的问题——用户中心的身份鉴权在大流量下很不稳定。因为用户中心需要维护的 Session Cache 空间很大,并且被各个业务频繁访问,那么缓存一旦出现故障,就会导致所有的子系统无法确认用户身份,进而无法正常对外服务。
这主要是由于 Session Cache 和各个子系统的耦合极高,全站的请求都会对这个缓存至少访问一次,这就导致缓存的内容长度和响应速度,直接决定了全站的 QPS 上限,让整个系统的隔离性很差,各子系统间极易相互影响。
那么,如何降低用户中心与各个子系统间的耦合度,提高系统的性能呢?我们一起来看看。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

使用Token算法降低用户身份鉴权的流量压力是一种有效的解决方案。传统的Session方式存在稳定性问题,因为用户中心需要维护的Session Cache空间大且容易出现故障。相比之下,JWT(JSON Web Token)的登录和token校验方式能够有效降低用户中心与各个子系统间的耦合度,提高系统性能。通过签名加密的token,用户信息被放入token中,无需与用户中心频繁交互请求,从而减轻了用户中心的压力。同时,token的刷新和离线验签也能保证系统的稳定运行。在安全建议方面,使用HTTPS协议通讯、限制token的更换次数、定期刷新token以及加强Web用户token的安全性都是必要的措施。总之,采用Token算法能够有效降低用户身份鉴权的流量压力,提高系统的性能和安全性。 文章还提到了其他类似的设计简化系统压力的方法,如文件crc32校验签名和Bloom Filter等,这些技巧在硬件能力腾飞的阶段仍然适用,可以大大提高系统的工作效率,减少系统的交互压力。 在思考题中,提出了用户更换昵称后如何快速更换token中保存的用户昵称的问题,这表明了作者对于Token算法的实际应用和可能遇到的问题有深入的思考。 总的来说,本文介绍了Token算法在降低用户身份鉴权流量压力方面的优势,以及相关的安全建议和其他简化系统压力的方法,为读者提供了有益的技术知识和思考。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《高并发系统实战课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(27)

  • 最新
  • 精选
  • 徐石头
    置顶
    Q1:在token过期很短的时候,通过refresh_token频繁更新token,怎么实现对用户实时管理?是不是还是跟用户人数相关,一般这种场景是后台系统,删除一个用户后该用户账号立刻不能登录,后台人数比C端人数少很多,所以管理起来代价比较小,更看重权限安全,放在缓存中进行管理。 A: 如果我来做快速更换昵称的功能,两种方式, a.在用户修改昵称后,内存中加入个用户标识,解析token后读取该标识,有则返回特定code,让客户端重新拿token。甚至可以不用客户端参与,返回301重定向到获取新token的路由。 b. token里面不存用户信息,只存用户ID,需要用户信息的时候从缓存读。

    作者回复: 你好,徐曙辉,很高兴收到你的再次留言 对于session 方式来说,由于用户每次请求都会读取session cache,客户端本地是不会保存token,所以不存在token内用户头像更新不及时问题。可以说后台系统用session管理用户很方便,因为这个可以做到用户实时管理,当我们禁用用户的时候把session的缓存登陆标志删掉即可。不过这个方式适合少量用户,对于QPS超过10w QPS请求的API则不太适合。 所以使用token方式来签名发给客户端,客户端请求其他子系统的时候,会带上它,子系统只要验证这个token的签名就不需要再去用户中心问一句。所以token使用后,用户中心不会被其他子系统频繁请求,但是也导致token发出去没法再次更改,即使我们用户中心给他拉黑了,其他子系统只认印章,不会过来问问。 同时为了方便token内会保存当前用户一些基础信息,减少其他系统过来询问的次数,这导致,用户更新头像,token没更换,是不会同步更新的 第一个很暴力,但是很有趣~ 第二个方式也很有趣,同时补一个技巧我们可以通过 设定 固定网址 user/用户uid/heaer.jpg方式直接获取用户头像,这样也不用考虑更新问题了

    2022-10-28归属地:北京
    11
    3
  • 极客
    客户端可以缓存修改后的昵称,直到更换了access token再清除缓存,类似弹幕本地先发送让用户自己认为发送成功了

    作者回复: 你好,极客,感谢你的留言,这个思路很有意思,是个方法,印象里这个技巧对于读多写多的服务的客户端也会做类似的事情

    2022-10-28归属地:北京
    9
  • 小林coding
    PAYLOAD 中定义的 token 发放时间 iat 字段的值是绝对时间戳,如果服务端的系统时间被往前修改了,这时在校验token是否过期的时候,是不是还需要增加一个处理:如果「当前时间戳 < token 发放时间戳 」,就认为 token 过期了。

    作者回复: 你好,小林,经常看你的公众号,这里建议如果只是一两秒建议忽略,原因在于,我们的服务器时间都是有误差的即使使用ntp定期同步也是存在误差,有时相差一两秒是很常见的,并且https也是基础时间做的加密,如果时间误差太大是无法通讯的。

    2022-11-15归属地:北京
    4
  • 7S
    access_token由于安全问题设置过期的时间非常短,但是refresh_token有效时间非常长,如果refresh_token被泄漏掉,是不是能一直刷新access_token呢。。

    作者回复: 你好,7S,很高兴收到你的思考,关于这里有一些特殊的小技巧,如请求时带上一些客户端特征,如:请求更换access_token时,带上的refresh_token的请求 同时 需要特殊的签名,存储在本地的token不用明文保存,与服务端通讯时用特殊协议加密等~

    2022-10-28归属地:北京
    3
    4
  • 林晓威
    老师好,请问光使用base64加密是不是不太安全?这样别人不是很容易知道你用什么加密算法了

    作者回复: 你好,林晓威,很高兴收到你的提问,这个算法重点并不是这个payload区,payload这里只是附带的数据,只是为了方便业务使用,事实上这个核心在于签名和过期时间,由于密钥是只有服务端有,所以签名是不能伪造的,如果到子业务这里验证签名是正确的密钥加密的,那么代表token的payload的内容肯定是服务器发放的,传输的用户无法更改,如果更改了就会和签名核对不上,通过这个方式就已经能够保证数据的安全了。至于base64内放的数据普遍是可以公开的信息,如果有不能公开的信息可以再做一层加密后再放入payload

    2022-11-07归属地:北京
    3
  • 吴晨辉
    很高兴第二次回答问题 传统sessoion会导致用户中心缓存大,耦合度高,但实时性强 jwt加密策略耦合度低,但是实时性不高 那么可以结合两个方式,优先读取token 加密字段,然后利用用户id关联session cache覆盖 考虑到session缓存成本,可以只缓存实时性强的字段,或者用vip制度,用户充钱越多,缓存的东西越多 核心思想就是成本增效

    作者回复: 最后一句很棒,支持,笑

    2022-10-31归属地:北京
    2
    3
  • 👽
    我的理解是,token中应该只存放和session生命周期同步的操作。比如:用户Id和权限。这两个东西,在用户session的生命周期内一般来说是不会变的。翻译一下,token代表着:你是谁,你能做什么。能做到这两个事情就够了。而不应该去单独关注用户的扩展信息。 至于昵称,我觉得应该单独放缓存中。通过用户ID获取。因为昵称当前token下修改还好说,如果跨token呢?比如web端修改了昵称web端端token可以立马换一个新的,移动端怎么办呢?所以我认为,昵称,头像,这种会修改的信息不应该放到token体里。

    作者回复: 你好,alien,确实如此,而很多业务为了方便,token有额外一段在结尾放附加消息

    2022-12-27归属地:北京
    2
  • xin
    徐老师,请问如何实现登出的时候,让token失效呢

    作者回复: 你好,可以在用户中心发个广播,让各个子系统订阅,子系统解开时对比下内部写的版本号

    2024-02-04归属地:四川
  • seker
    徐老师,请问,用于token加密头中的常用加密算法有哪些呢?

    作者回复: 你好,seker,可以参考这个列表 https://jwt.io/libraries

    2023-08-16归属地:广东
  • 无问西东
    你好,客户端保存token如何保证不被其他应用窃取呢

    作者回复: 你好,这个看对安全要求程度。太过复杂会有些难用,简单的方式token可以加密保存在本地存储或数据库内如localstorage,sqlite,每次请求再次加密传输,定期更新短期token等

    2023-07-26归属地:上海
收起评论
显示
设置
留言
27
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部