简介

SSO 是 single sign-on 的缩写,国内统称单点登录,其实翻译为单一登录更为准确,因为其内涵就是对于多系统的场景下,只进行一次登录即可访问所有子系统资源。

[注]:阅读前需掌握前置知识 JWT,Session 和 Cookie。

流程

SSO 的标准实现包含以下几类角色:

  1. 认证中心(Central Authentication Server)
  2. 子系统(Subsystem Server)
  3. 用户(User)

其中认证中心是唯一实现登录功能的服务器,子系统不提供登录功能。

流程大致如下:

  1. 未登录的用户访问子系统时,请求会被子系统转发到认证中心;
  2. 认证中心再使用户重定向到登录页;
  3. 用户输入账号信息点击登录;
  4. 认证中心验证登录信息,创建 Global Session 和 SSO Token,再将请求重定向到子系统,此时会附带上 SSO Token;
  5. 子系统收到请求,再请求认证中心验证 SSO Token;
  6. 认证中心验证 SSO Token 正确无误后,再生成一个 JWT,其 payload 中包含用户信息,将 JWT 返回给子系统;
  7. 子系统解析 JWT 获得用户信息,以 Local Session 形式存储,返回用户想要访问的初始资源,同时令浏览器生成 cookie;
  8. 用户访问子系统 2 时,请求同样会被重定向到认证中心,但不同的是此时会携带 cookie;
  9. 认证中心通过 cookie 中的 session id,从 Global Session 中还原用户之前登录过程中涉及到的信息(主要是 SSO Token),然后转发请求到子系统 2,注意此时跳过了登录逻辑;
  10. 子系统 2 经过相同的流程(5,6,7)后,用户直接跳过登录,访问到子系统 2 资源;

SSO Token 并不包含用户信息,主要作用是让认证中心确认子系统的身份,确认身份后再用私钥签发包含用户信息的 JWT,子系统通过公钥验签,从而确认用户信息的正确性(当然也可以采用对称加密);

子系统转发请求时一般要附带上用户所访问的 URL(一般以查询字符串形式传递用户要访问的URL),然后认证中心在用户登录成功时,可以将用户重定向回子系统。

前端

前端实现需要注意的点:

  1. 登录:调用登录接口时,一般要附带上当前URL,以便登录后重定向回当前页面;
  2. 鉴权:
    1. 用户未登录时不加载应用,只加载登录相关逻辑;
    2. 用户未登录时加载部分应用,限制其访问未授权的页面,此时可通过动态加载技术,按路由分离 chunk,实现按需加载(懒加载),提高首屏渲染速度;
    3. 用户登录后的鉴权也可以按照上述思路实现及优化;
  3. Token:
    1. 前端存储:一般存储在 localStorage,而非 cookie,主要是为了防止 CSRF 攻击;
    2. 过期处理:过期 token 无法通过服务器端校验,一般会返回 403 Forbidden,需要在前端请求库全局添加处理逻辑,即清空数据,重新登录等;
      1. 重新登录也分多种情况:
        1. 对于采用标准的认证中心统一处理 SSO 的系统,只需要清空 token,重新发起请求即可,甚至子系统也可以代为实现,直接将请求重定向到认证中心;
        2. 对于非标准的实现,如果服务器不发送重定向到登录页的响应,就需要客户端实现跳转登录页的逻辑;
    3. 延长有效期,优化用户体验:
      1. 服务器端实现,客户端无需额外处理:在服务器端以 token 为 key、value 缓存起来,缓存有效期比 token 有效期要长,当 token 失效时直接生成新 token 覆盖缓存的 value,重置缓存过期时间, 服务器端基于缓存的 value 进行各种校验;
      2. refresh token:服务器端生成 refresh token,提供刷新 token 的接口,客户端在收到 token 过期响应时,通过传递 refresh token 调用刷新 token 接口,延长 token 有效期;