Session共享问题有以下几种方案:

  • Session复制,session发生变化,集群中的服务器将会进行同步
  • 牵一发而动前身,某个session发生变化,所有服务器都要进行同步
  • 集群机器数量大或者用户数量大时,同步的网络开销也就越大
  • 每台服务器都含有session,造成数据冗余,资源浪费
  • Session集中存储
  • 实现简单,无需依赖应用层
  • 可以通过重写HttpSession、或者Tomcat的Session机制,来实现无侵入的Session共享
  • 通常使用Redis作为存储引擎
  • 基于Cookie机制
  • 生成Token,写入Cookie中,每次请求浏览器将会带着Token到服务端
  • 服务端根据Token识别用户的状态
  • 此方式实现简单、不影响服务端性能,但是具有安全问题

基于Cookie机制

JWT

jwt是一种令牌机制,目前共有两种令牌类型:

  • 透明令牌
  • By Reference Token
  • 随机字符串,无法猜测,严格服务器集中校验
  • 自包含令牌
  • By Value Token
  • 可以包含用户元数据或者声明(claims),无状态校验
  • 如,JSON Web Token

JSON Web Token,是客户端和服务端信息安全传递以及身份认证的一种解决方案。JWT由三个部分组成:

  • header
  • playload
  • signature

所以,JWT的格式通常如下:

xxxxx.yyyyy.zzzzz

// 比如
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Header:

{
  "alg": "HS256", // 使用的签名算法
  "typ": "JWT" // token的类型
}

此部分经过Base64编码称为JSON Web Token的第一部分。

Payload:

Payload可以称为载荷,用于承载具体的数据,包含实体数据。其中包含claims,是对数据的声明,共有三种类型:

  • Registered claims:已注册Claims,是一组预定义的声明,非强制,但是不强制使用。包含 iis(发行人)、exp(到期时间)、sub(主题)、aud(观众)等。
  • Public claims:由使用JWT的人随意定义。
  • Private claims:
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

然后,Payload经过Base64Url编码,形成JSON Web Token 的第二部分。

Signature:

生成签名,由 encode header . encode payload使用header的alg签名算法与指定的secret进行签名。从而保证信息不被篡改、发件人是否属实。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)
认证流程
  1. 客户端登录、服务端生成Token
  2. 服务端将Token返回给客户端,客户端存储Token到Cookie或者localstorage中
  3. 客户端携带token调用api,校验token并处理响应
  4. 为了保证Token的有效性,需要制定Token刷新机制
JWT 优劣

优点:

  • CORS
  • 不需要CSRF保护
  • 无状态校验
  • 不需要分布式存储
  • 减少服务器压力

缺点:

  • 信息公开可见
  • 易受XSS攻击
  • 可能包含过期授权信息
  • 令牌大小随信息量增长
  • 无状态与吊销互斥

如果需要更严格的方式,需要使用透明令牌+集中校验的方式。