单点登录

什么是单点登录?

举个场景,假设我们的系统被切割为N个部分:商城、论坛、直播、社交…… 如果用户每访问一个模块都要登录一次,那么用户将会疯掉, 为了优化用户体验,我们急需一套机制将这N个系统的认证授权互通共享,让用户在一个系统登录之后,便可以畅通无阻的访问其它所有系统。

单点登录可以做到:**在多个互相信任的系统中,用户只需登录一次,就可以访问所有系统。**

三种单点登录模式

1: 前端同域,后端同Redis

2: 前端不同域,后端同Redis

3: 前端不同域,后端不同Redis

前端同域,后端同Redis

这种情况,多个前端部署的域名同域,后端可以访问同一个Redis。我们可以通过共享Cookie的方式进行单点登录。

1: 使用共享Cookie的方式来解决前端Token共享的问题

2: 使用Redis在不同的后端来解决Session共享的问题

所谓共享Cookie,就是主域名Cookie在二级域名下的共享,举个例子:写在父域名stp.com下的Cookie,在s1.stp.coms2.stp.com等子域名都是可以共享访问的。

前端不同域,后端同Redis

这种情况会导致我们共享Cookie方式失效,我们需要再不同域中传递Token。

  1. 用户在 子系统 点击 [登录] 按钮。

  2. 用户跳转到子系统登录接口/sso/login,并携带back参数

    记录初始页面URL。

    • 形如:http://{sso-client}/sso/login?back=xxx
  3. 子系统检测到此用户尚未登录,再次将其重定向至SSO认证中心,并携带redirect参数记录子系统的登录页URL(后面SSO登录成功跳转页面)。

    • 形如:http://{sso-server}/sso/auth?redirect=xxx?back=xxx
  4. 用户进入了 SSO认证中心 的登录页面,开始登录。

  5. 用户 输入账号密码 并 登录成功,SSO认证中心再次将用户重定向至子系统的登录接口/sso/login,并携带ticket码参数。

    • 形如:http://{sso-client}/sso/login?back=xxx&ticket=xxxxxxxxx
  6. 子系统根据 ticket码SSO-Redis 中获取账号id,并在子系统登录此账号会话。

  7. 子系统将用户再次重定向至最初始的 back 页面。

image-20230505114157693

前端不同域,后端不同Redis

  1. Client 端无法直连 Redis 校验 ticket,取出账号id。
  2. Client 端无法与 Server 端共用一套会话,需要自行维护子会话。
  3. 由于不是一套会话,所以无法“一次注销,全端下线”,需要额外编写代码完成单点注销。

需要注意的是,做好接口鉴权,防止恶意请求调用,泄露用户信息。

解决方案就是使用Http请求SSO-SERVER,将获取信息获取同步到本地客户端进行保存。

除了账号id,我们可能还需要将用户的昵称、头像等信息从 Server端 带到 Client端,即:用户资料的同步。

在模式二中我们只需要将需要同步的资料放到 SaSession 即可,但是在模式三中两端不再连接同一个Redis,这时候我们需要通过http接口来同步信息:

如何注销

  1. Client 端在校验 ticket 时,将注销回调地址发送到 Server 端。
  2. Server 端将此 Client 的注销回调地址存储到 Set 集合。
  3. Client 端向 Server 端发送单点注销请求。
  4. Server 端遍历Set集合,逐个通知 Client 端下线。
  5. Server 端注销下线。
  6. 单点注销完成。
image-20230505140104298