从0到1手撕鉴权系统架构(三)–单点SSO的架构设计

概念很大,你忍一下。

单点登陆要解决的是多系统、跨域名,但只需登陆一次即可全局通用。
有2个难点

  1. 怎么保证1次登陆以后所有子系统都不用再登陆?
  2. 跨域了怎么办?

怎么保证 1 次登陆以后所有子系统都不用再登陆?

首先怎么解决用户登陆后,发送的请求服务端都知道是该用户发的?

常见的做法有:

  1. 登陆成功后服务端返回 token,此后客户端的请求都将 token 放入请求头的 Authorization 中。
  2. 登陆成功后服务端将 SESSIONID 写入 cookie。

下次请求会自动带上 token,这样服务器就知道这次请求属于那个用户。

如果在系统 A 登陆过,要求在系统 B 中不用再次登陆,后端应该如何设计?

image.png

image.png

要做到这样,只需要两点:

  1. 首先数据层要求所有系统的用户都保存着 SSO 系统中。即上一篇的用户表(只用存用户的基本公用信息,其他信息以扩展表形式存在不同的系统,id 关联)。
  2. 系统 A 的登陆态得让系统 B 拿到。

1 已经在数据库表设计的时候解决了,着重解决 2。

2 分两种情况,如果是从 A 系统跳转到 B 系统,那么可以直接将 token 放在链接中一并跳转,这样 B 系统通过解析参数可以直接拿到 A 系统的登陆态;如果全新打开 B 系统主页,那么可以将登陆态存放在 cookie 中,同一个域名的 cookie 是通用的(这里会涉及不同域名情况,后面说)。

截止现在,B 系统已经拿到 A 系统的登陆态了,怎么换成 B 系统的登陆态呢?

这里也要看系统之间怎么设计的。如果系统 A 和 B 共用一个 token,自然不需要额外操作了。大部分情况下,系统 A 和 B 不是同一个 token,那么额外需要一个步骤,系统 B 请求 SSO 服务器通过系统 A 的 token 换取系统 B 的token。

来个流程图示意下。

image.png

token 怎么储存?

token 建议存在 redis 中。

定义好 token 的储存规范,只需要在登出时清理掉所有系统的 token 即可保证全部登出。

例如,各个系统 token 存在同一个 key,在 value 中区分,key 使用各个 token 想通的前 10 位;不同系统 token 存不同 key,但同一个用户的不同系统之前 key 有关联。及保证任意一个系统请求的登出,可以找到其他系统 token 并清理。

来个流程图。

image.png

跨域了怎么办?

  1. url 携带 token 跳转
  2. cookie 设置想通的 domain 和 path
  3. 一个域获取 token 后,js 主动把 token 存在其他域中。