【SSO单点登录】JWT如何防篡改&&主动注销【黑白名单机制】

2,808 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第 4 天,点击查看活动详情

大家好,我是melo,一名大三后台练习生,不知不觉练习时间长达一年了!!!

👉本篇速览

  • JWT残留的问题
    • 如何防止JWT被篡改?
      • 扩展-- 数字签名
    • 主动注销
      • 白名单机制
      • 黑名单机制
    • 续签问题
      • OAuth2.0的refresh token刷新机制

🎈如何防止token被篡改?

假设前端泄露了token,黑客拿到token之后,也没办法同时篡改Header 、Payload、 Signature三部分。

这是为什么呢? 因为Signature部分的加密算法:HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

即使黑客修改了header,payload,但由于不知道secret,也就没法生成篡改后,应当对应的Signature。

  • 而后服务端校验的时候,会解析出其中包含的 Header、Payload 以及 Signature 。服务端会根据 Header、Payload、密钥再次生成一个 Signature。拿新生成的 Signature 和 JWT 中的 Signature 作对比,如果一样就说明 Header 和 Payload 没有被修改,不一样就说明被篡改,校验不通过。

不过,如果服务端的秘钥secret也泄露的话,黑客就可以同时篡改 Signature 、Header 、Payload 了。黑客直接修改了 Header 和 Payload 之后,再重新生成一个 Signature 就可以了。

所以秘钥secret一定保管好,不能泄露出去。JWT 安全的核心在于签名,签名安全的核心在秘钥。

扩展 -- 数字签名

其实就是JWT中的Signature

  1. Bob将原文md5加密后,再用私钥对md5加密后的结果加密,变成一个sign,一并传给Pat【用于校验】
  2. Pat收到后,用公钥解密,得到原文md5加密后的结果, 再对传过来的文章进行md5加密,判断两个md5的结果是否一致

关键就在于,黑客不知道私钥,也就没法篡改原文后,生成跟原文对应的sign,两者对应不上

本文先简单聊聊数字签名,具体HTTPS中的应用,以及微信支付如何确保数据安全,我们之后有机会再出一片文章单独谈谈

🎈主动注销

上文我们谈到,一般注销只需要前端销毁存储在客户端的token即可,但那样的话,其实token本质上是还能用,一旦泄露了,你的登录状态就能被别人利用

但jwt又没办法主动过期,此时就需要借助第三方的方式,来让token“过期”,提到过期,我们很快就想到了Redis。

白名单机制

  1. 白名单机制认证通过时,把JWT存到Redis中。注销时,从缓存移除JWT。请求资源添加判断JWT在缓存中是否存在,不存在拒绝访问。

这种方式和cookie/session机制中的会话失效删除session基本一致,但同时也违背了JWT的初衷,每次登录,我们都需要存储token,跟session一样有内存开销问题

黑名单机制

  1. 黑名单机制注销登录时,缓存JWT至Redis,且【缓存有效时间设置为token的剩余有效期即可】,请求资源时判断是否存在缓存的黑名单中,存在则拒绝访问。

白名单和黑名单的实现逻辑差不多,但黑名单不需每次登录都将JWT缓存,仅仅在某些特殊场景下需要缓存JWT,给服务器带来的压力要远远小于白名单的方式。

只有主动注销的场景下,才需要缓存JWT 其他情况下如token自动过期,都不需要

黑名单机制,巧妙的解决了存储的问题,而且存储量是远远小于,大多数情况下,登录状态都是token自动过期了,而不是用户主动注销。

因此,相比之下黑名单更讨喜~

💠下篇预告

  • 本篇就上篇残留的两个jwt安全问题【篡改+虚假注销】展开了解读,虽然还有很多解决方式和可扩展的点,限于篇幅,我们之后再单独拎出来详谈。
  • 下篇我们重点关注token的续签问题,并搭配 OAuth2.0 中的refresh token刷新机制一同食用,敬请期待~

🧿友链