Skip to content
大纲

Single Sign On(SSO)

单点登录:在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统。

同域下的单点登录

通过三级域名(app.xxx.com)区分应用,可以设置二级域名下的 cookie,利用三级域名可以访问二级域名的方式,实现 cookie 在不同应用之间的传递。

跨域下的单点登录

使用 CAS 流程实现,该流程是单点登录的标准流程

  1. 未登录用户访问 app,跳转到 CAS Server (SSO 登录系统)
  2. SSO 登录认证后,将登录状态写入 SSO 的 session,浏览器端记下 SSO 域的 cookie
  3. SSO 登录完成后生成一个 Service Ticket,跳转至 app 并传递该数据
  4. app 获取 Service Ticket 后向后端请求验证是否有效
  5. app 验证通过后记下 session 并设置 app 域的 cookie

NOTE

  • Service Ticket 通常保存在 redis 中

JSON Web Token(JWT)

JWT 是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准,适用于分布式站点的 SSO 场景

传统的 session 认证

客户端存储 cookie 用于标识用户,服务端根据 cookie 进行 session 认证;

session 认证的问题

  • session 通常存储于内存中,用户的增多会提高服务端的开销
  • 由于认证存储于内存中,在分布式的应用上,限制了负载均衡器的能力
  • cookie 若被截获容易受到 CSRF 攻击

基于 token 的鉴权机制

工作流程

  1. 用户登录
  2. 服务器验证登录信息
  3. 服务器通过验证发送 token
  4. 客户端存储 token 并在每次请求时附送上 token
  5. 服务端验证 token 后进行正常处理流程

该 token 需要保存在请求头中,服务端需要支持 CORS 策略

JWT 组成部分

JWT 是三段用 . 连接的字符串,包括头部、载荷、签名

头部

包括声明类型和声明加密算法,如

json
{
  "typ:": "JWT",
  "alg": "HS256"
}

然后对头部进行 base64 转换生成第一部分字符串

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

载荷

用于存放有效信息,包括

  • 标准中注册的声明
    • iss: jwt 签发者
    • sub: jwt 所面向的用户
    • aud: 接收 jwt 的一方
    • exp: jwt 的过期时间,这个过期时间必须要大于签发时间
    • nbf: 定义在什么时间之前,该 jwt 都是不可用的.
    • iat: jwt 的签发时间
    • jti: jwt 的唯一身份标识,主要用来作为一次性 token,从而回避重放攻击。
  • 公共的声明:可添加任何非敏感信息,该部分可被解密
  • 私有的声明:提供者和消费者共同定义的声明,该部分可被解密

然后对头部进行 base64 转换生成第二部分字符串

签名

js
// 生成方式如下
var encodedString = Base64.encode(header) + "." + Base64.encode(payload);
// NOTE: 后端生成,secret 为服务端数据,不能暴露给客户端
var signature = HMACSHA256(encodedString, secret);

使用

js
const url = "";
const token = ""; // JWT
fetch(url, {
  headers: {
    Authorization: "Bearer" + token,
  },
});

小结

由于 JWT 签名部分在服务端生成,可以避免数据被篡改

头部和载荷部分使用 Base64 转换,可以被解析

JWT 相较于 session 少了缓存机制,在使用中无法废止,通常需要设置一个有效期