状态管理

五十岚2020年2月18日
大约 3 分钟

有/无状态协议

1. 协议状态

七层网络协议,大多都是有状态协议,如 SMTP ,但 HTTP 协议,则是无状态协议

1.1 有状态协议

SMTP 协议

  • 发送前必须先建立 TCP 连接,并发送 HELO/EHLO 建立会话
  • 然后进入 AUTH 认证
  • 认证通过才可以发送数据
  • 通过 QUI 命令关闭会话

如上,整个通信过程,双方是必须要时刻记住当前连接的状态的,不同状态能接受的命令是不同的。另外,之前命令传输的某些数据也必须要记住,因为可能会对后续的命令产生影响

这种有记忆功能的,就是有状态协议,通常维护状态代价较高

1.2 HTTP1.X 无状态协议

指协议对于交互性场景,没有记忆能力

  • 每个请求(交互)都是独立的,本次请求不会基于上次请求有任何改变
    • 比如:用户登录,和把东西加入购物车,HTTP 不会去记录谁 和 他干了什么,是 完全无依赖
  • 没有记忆能力,即无存储
    • 因此需要外部、如 CookieSession 等为交互存储状态
  • TCP/IP 不同,发过去就断开了
  • 减少服务器的 CPU 和 内存 开销

英文翻译为 甜品,使用 Cookie 可自动填写用户名、记住密码等,算是给用户的一点甜头

3. Session

因为存入 Cookie,有泄密风险,因此将机密信息存入服务器,通过服务器来维护客户档案

  • 可以理解为服务端存储了一张 User 表SessionID 即该表主键
  • 占用服务器资源,用户都要去 Session 服务器授权,因此限制负载均衡能力
  • 可以CSRF 跨域伪造请求,依然泄密

4. Token

令牌鉴权,不存用户信息了,采用不同的加密方式进行数字签名

  • 用户访问服务器去到加密后的令牌,后续访问直接使用令牌即可
  • 哪怕下次访问负载均衡的其他节点,也可以根据令牌进行鉴权
  • 坏处是依然需要查库(去数据库查询认证信息,进行鉴权)

因此为了服务器不存储、不查库、能鉴权,诞生了如今的 JWT

5. JWT

时下最流行的跨域认证解决方案

JWTopen in new window 全称 JSON Web Token 它可以将所有信息都以 JSON 格式存储,包括 用户名、密码、加密信息等

5.1 组成部分

通常由三部分组成,它们之间用圆点 . 连接

  • Header: 两部分组成,包括 token 类型 & 加密算法(HMAC SHA256 或者 RSA

    {
      "alg": "HS256",
      "typ": "JWT"
    }
    
  • Payload: 包含声明,指关于用户和其他数据的声明,存放实际传递的数据,有三种类型:

    • Registered claims: 预定义声明,非强制,如:iss (issuer), exp (expiration time), sub (subject), aud (audience)
    • Public claims: 可随意定义
    • Private claims: 用于在同意使用它们的各方之间共享信息,并且不是注册的或公开的声明
    {
      "sub": "1234567890",
      "name": "john",
      "admin": true
    }
    

    payload 进行 Base64 编码就会得到 JWT 的第二部分

注意: 不要在 payloadheader 中放置敏感信息,因为默认是不加密的

  • Signature: 对上面两部分的签名,防止消息被篡改

    需要指定一个只有服务器知道的密钥(secret )不能泄露给用户,然后按照如下形式生成签名

    HMACSHA256(
      base64UrlEncode(header) + "." +
      base64UrlEncode(payload),
      secret)
    

5.2 JWT 使用方式

客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 LocalStorage

此后,客户端每次与服务器通信,都要带上这个 JWT

可把它放在 Cookie 里自动发送,但这样不能跨域。更好的做法是放 HTTP 请求头Authorization字段里

Authorization: Bearer <token>

另一种是,跨域的时候,JWT 就放在 POST 请求的数据体里面

上次编辑于: 2023/3/19 09:20:05