在 oauth 的第三方认证体系中,每一个认证节点拿到的凭证就是JWT的格式
cookie - session模式
先对比一下老的 cookie - session 的认证信息的模式:
由于session 信息存储在服务器里面,结合 浏览器的同源策略 和 HTTPS 的传输层安全保证,安全性存在先天优势。
对于单体应用, cookie - session 的模式还是不错的
但是需要开始扩展多服务器的时候,其劣势就开始显现了, 因为 session 是存储在服务器的内存里面,按照 CAP 理论,需要选择下面一个方案:
- 牺牲 C - 一致性 : 每一个用户转发到固定的节点,判断其固定的session信息,如果节点崩溃了,那么存储的状态就消失了
- 牺牲 A - 可用性: 选择session 复制的逻辑,挂了一个节点不至于全部没了,但是session复制是一个高额的开销
- 牺牲 P - 分区容忍性: 单节点统一存储session信息
对于单个客户端,多个服务端的场景,JWT存储认证无状态就是一个标准答案
JWT介绍
JWT - JSON WEB TOKEN
JWT是无状态的,令牌中包含了用户信息以及令牌的签名。这意味着在多台服务器之间进行负载均衡时,不需要在服务器之间共享会话信息。每个请求都可以独立验证,从而更容易实现分布式架构
HEADER:记录令牌类型、签名算法(比如 HMAC)
HMAC : 散列消息认证码 , 传统的hash函数只能保证内容没有被篡改,但是 hmac 是使用了携带秘钥的hash算法,可以保证该hash是由持有秘钥的人生成的
PAYLOAD:携带的真实有效的信息,一般这里不能携带什么敏感的内容
VERIFY SIGNATURE : 秘钥 + hash 函数 完成的内容签名; 先hash 内容,然后秘钥对hash 后的结果加密 , 接收方解密后获取hash内容 , 在对比对 PAYLOAD hash的结果,判断 PAYLOAD 有没有被修改
JWT是一个无状态的认证标识,可伸缩能力很好
缺点:
- 令牌难以主动失效: 服务器需要额外逻辑完成失效逻辑,如自动退出如何失效,这里需要一个具体的设计;例如黑名单的设计,既然存在黑名单了,那么就会存在部分状态化的设计
- 重放攻击: JWT 使用重放攻击如何去识别呢? 因为偏无状态,就很被动
- 携带的信息有限:虽然 HTTP协议没有规定header长度,但是服务器、浏览器都会存在限制,比如 Tomcat限制 8KB , Nginx 默认是 4KB
- 令牌在客户端如何保存: 我们不能接受关闭一个标签页登录就失效了,那么浏览器那边如何存储? local storage 等可能都会存在一个泄露的风险
- 无状态的一些弊端:在线用户实时统计????