created_at | updated_at | slug | tags | ||
---|---|---|---|---|---|
2022-08-10 04:26:55 -0700 |
2022-08-10 04:26:55 -0700 |
how-to-use-token-safely |
|
通常在带有登录功能的业务中,我们会向用户(客户端)发放访问凭证,往后一段时间,用户持该凭证即可在应用内畅行。不同应用可能有不同的名字:access_token、token、xxxid,也可能有不同的形式:不透明字符串、JWT等。本文讨论访问凭证的安全性。
考虑到一般发放JWT的系统都将其当做无状态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失活机制:超过n天未使用的token主动失效
- token滚动机制:如果用户通过登录或刷新触发了新token的生成,则之前的token设为无效。
- token驱逐机制:提供交互让用户选择主动驱逐token
- 限制token的使用环境
- 将token和用户使用环境绑定起来,验证token时同步验证环境。稳定可用可获取的环境包括
- 设备型号:永远不会变
- 操作系统版本:只会升级,不会降级
- app版本:只会升级,不会降级
- 设备ID:至少单次会话期间是稳定的
- 将token和用户使用环境绑定起来,验证token时同步验证环境。稳定可用可获取的环境包括
- token使用行为监测,分析出敏感操作
我们常用的Google、Bilibili、微博等网站和应用,似乎登录一次就再也不需要登录,通过抓包的方式去查看它们的访问凭证,会怀疑它们很可能发放了一个长期有效的凭证,按上面的分析,长期的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天未访问,将自动过期,强制用户重新登录