简介
SSO 是 single sign-on 的缩写,国内统称单点登录,其实翻译为单一登录更为准确,因为其内涵就是对于多系统的场景下,只进行一次登录即可访问所有子系统资源。
[注]:阅读前需掌握前置知识 JWT,Session 和 Cookie。
流程
SSO 的标准实现包含以下几类角色:
- 认证中心(Central Authentication Server)
- 子系统(Subsystem Server)
- 用户(User)
其中认证中心是唯一实现登录功能的服务器,子系统不提供登录功能。
流程大致如下:
- 未登录的用户访问子系统时,请求会被子系统转发到认证中心;
- 认证中心再使用户重定向到登录页;
- 用户输入账号信息点击登录;
- 认证中心验证登录信息,创建 Global Session 和 SSO Token,再将请求重定向到子系统,此时会附带上 SSO Token;
- 子系统收到请求,再请求认证中心验证 SSO Token;
- 认证中心验证 SSO Token 正确无误后,再生成一个 JWT,其 payload 中包含用户信息,将 JWT 返回给子系统;
- 子系统解析 JWT 获得用户信息,以 Local Session 形式存储,返回用户想要访问的初始资源,同时令浏览器生成 cookie;
- 用户访问子系统 2 时,请求同样会被重定向到认证中心,但不同的是此时会携带 cookie;
- 认证中心通过 cookie 中的 session id,从 Global Session 中还原用户之前登录过程中涉及到的信息(主要是 SSO Token),然后转发请求到子系统 2,注意此时跳过了登录逻辑;
- 子系统 2 经过相同的流程(5,6,7)后,用户直接跳过登录,访问到子系统 2 资源;
SSO Token 并不包含用户信息,主要作用是让认证中心确认子系统的身份,确认身份后再用私钥签发包含用户信息的 JWT,子系统通过公钥验签,从而确认用户信息的正确性(当然也可以采用对称加密);
子系统转发请求时一般要附带上用户所访问的 URL(一般以查询字符串形式传递用户要访问的URL),然后认证中心在用户登录成功时,可以将用户重定向回子系统。
前端
前端实现需要注意的点:
- 登录:调用登录接口时,一般要附带上当前URL,以便登录后重定向回当前页面;
- 鉴权:
- 用户未登录时不加载应用,只加载登录相关逻辑;
- 用户未登录时加载部分应用,限制其访问未授权的页面,此时可通过动态加载技术,按路由分离 chunk,实现按需加载(懒加载),提高首屏渲染速度;
- 用户登录后的鉴权也可以按照上述思路实现及优化;
- Token:
- 前端存储:一般存储在 localStorage,而非 cookie,主要是为了防止 CSRF 攻击;
- 过期处理:过期 token 无法通过服务器端校验,一般会返回 403 Forbidden,需要在前端请求库全局添加处理逻辑,即清空数据,重新登录等;
- 重新登录也分多种情况:
- 对于采用标准的认证中心统一处理 SSO 的系统,只需要清空 token,重新发起请求即可,甚至子系统也可以代为实现,直接将请求重定向到认证中心;
- 对于非标准的实现,如果服务器不发送重定向到登录页的响应,就需要客户端实现跳转登录页的逻辑;
- 重新登录也分多种情况:
- 延长有效期,优化用户体验:
- 服务器端实现,客户端无需额外处理:在服务器端以 token 为 key、value 缓存起来,缓存有效期比 token 有效期要长,当 token 失效时直接生成新 token 覆盖缓存的 value,重置缓存过期时间, 服务器端基于缓存的 value 进行各种校验;
- refresh token:服务器端生成 refresh token,提供刷新 token 的接口,客户端在收到 token 过期响应时,通过传递 refresh token 调用刷新 token 接口,延长 token 有效期;