• 如何安全地使用token


    通常在带有登录功能的业务中,我们会向用户(客户端)发放访问凭证,往后一段时间,用户持该凭证即可在应用内畅行。不同应用可能有不同的名字:access_token、token、xxxid,也可能有不同的形式:不透明字符串、JWT等。本文讨论访问凭证的安全性。

    考虑到一般发放JWT的系统都将其当做无状态token使用,不适用本文讨论范文,故忽略。

    原则

    总的说来,应该在如下两方面做好

    • 用户体验:登录操作成本很高,不能经常让用户重新登录,会劝退。最离线的情况是:正常用户永远能够正常使用
    • 安全性:token不能丢,即使丢失,风险也应当可空

    分别讨论

    用户体验

    两种方式可使得用户免于重新登录

    • 发放一个永不过期的token
    • 发放一个短期的token,到期后主动刷新token,效果和永久token一致

    Token安全性

    风控系统将防御分为事前、事中、事后。类似地,我们可以套用

    • 事前:如何防御token不丢失
    • 事后:token丢失后如何使得损失最小

    不丢Token

    • 防中间人:HTTPS协议、客户端屏蔽代理、客户端预埋证书
    • 防XSS:web将token放在Cookie并添加httpOnly和Secure属性,防XSS导致的token泄露
    • 防CSRF:csrf token

    Token丢失后止损

    如果token丢失,短时间内造成的损失不可挽回,只能考虑如何止损

    • 尽快让token失效,有几种方式,可以叠加使用
      • token过期机制:token限制有效期,过期自动失效
      • token失活机制:超过n天未使用的token主动失效
      • token滚动机制:如果用户通过登录或刷新触发了新token的生成,则之前的token设为无效。
      • token驱逐机制:提供交互让用户选择主动驱逐token
    • 限制token的使用环境
      • 将token和用户使用环境绑定起来,验证token时同步验证环境。稳定可用可获取的环境包括
        • 设备型号:永远不会变
        • 操作系统版本:只会升级,不会降级
        • app版本:只会升级,不会降级
        • 设备ID:至少单次会话期间是稳定的
    • token使用行为监测,分析出敏感操作

    讨论

    为什么大公司可以发长期token?

    我们常用的Google、Bilibili、微博等网站和应用,似乎登录一次就再也不需要登录,通过抓包的方式去查看它们的访问凭证,会怀疑它们很可能发放了一个长期有效的凭证,按上面的分析,长期的token一旦丢失将造成无可挽回的损失,这样岂不是很不安全?原因主要还是他们有自己的风控系统,能够根据用户使用环境、行为习惯识别风险,采取主动失效、通知用户等操作及时止损。

    一篇文章自觉不错:这里

    refresh_token如何?

    大公司有风控系统,有足够的底气发长时token,小公司没有风控系统,发长时token无异于作死,看起来token刷新是一个不错的办法。

    access_token + refres_token的组合很多人都熟悉,知道它大多源自OAuth2协议,前者用于访问,后者用于刷新得到新的token。Auth0在refresh_token上又增加了令牌轮换和重用检测机制保障刷新操作的安全

    • 令牌轮换:执行token刷新后,原refresh_token会失效,换发新的refresh_token,减轻了refresh_token泄露的风险
    • 重用检测:当检测到已经被用过的refresh_token刷新操作时,说明refresh_token已经泄露,此时服务将所有access_token和refresh_token都失效,强制用户重新登录,进一步保证了refresh_token的安全性

    参考文档

    没有令牌轮换和重用检测的refresh_token机制是不安全的。一种说法是refresh_token传输频率较低,所以安全,但在当前HTTPS标配的情况下,中间人攻击已不容易,诚然降低的传输频率会增加一点安全性,但没有本质的变化,相对鸡肋。

    方案

    提一个适用于仅在用户系统中保障token安全性的方案,主要包含如下几个部分

    • 简单的风控:token验证时同时验证设备型号、操作系统(可从UA获取)、设备ID,如不一致说明token可能丢失
    • 短期的token:token有效期两个小时(根据需求自定义)
    • token刷新
      • access_token和refresh_token都是一个token,不引入refresh_token:token有过期时间,也有刷新的过期时间
      • 令牌轮换:token刷新后,将换发新的token,且原token不能再用于刷新
      • 重用检测:当检测到已经被用于刷新的token再次执行刷新操作,将所有token都失效,强制用户重新登录
    • token活动检测机制:记录token访问时间,如果token超过x天未访问,将自动过期,强制用户重新登录
  • 相关阅读:
    甘露糖-阿霉素mannose-Doxorubicin|甘露糖-聚乙二醇-阿霉素,Doxorubicin-PEG-mannose
    spring boot 3.0如何优雅的使用s3协议连接minio
    苹果电脑维护工具:CleanMyMac X让你的Mac焕发新生!
    华为telnet的两种认证方式
    从Mysql架构看一条查询sql的执行过程
    vasp频率计算出错Intel MKL error
    MySQL高级篇知识点——索引优化与查询优化
    C++ Decltype 关键字
    网络请求-Android篇(Okhttp和Retrofit)
    python数据可视化-matplotlib入门(5)-饼图和堆叠图
  • 原文地址:https://blog.csdn.net/zou8944/article/details/126264125