avatar

单点登录的两种实现方案


传统的登录方案中,用户每访问一个站点都需要先输入用户名密码进行登录。当这些站点接入单点登录(Single Sign On, SSO)系统之后,用户只需要在第一次访问的站点中登录一次,那么用户对其它接入该SSO系统的站点就都拥有了访问权限。

flowchart LR
A1[Application1]
A2[Application2]
A3[Application3]
S[SSO]
A1 --> S
A2 --> S
A3 --> S

同源策略

在设计单点登录系统之前,需要搞清楚浏览器的同源策略

  1. cookie在不同域名下不能共享。如a.com的站点不能访问b.com的cookie,也不能为b.com设置cookie
  2. 子域名可以设置父域名(eTLD除外)的cookie,也可以访问父域名的cookie,即父域cookie被所有子域共享

基于认证中心的标准实现方案

用户首次访问时,需要在认证中心登录:

sequenceDiagram
participant B as 浏览器
participant A as 系统A(a.com)
participant S as 认证中心(sso.com)

B->>+A: 访问受保护页面<br>a.com/pageA
A->>A: 验证未登录
A-->>-B: sso.com/login?redirect=a.com/pageA
B->>+S: 访问sso.com<br>sso.com/login?redreict=a.com/pageA
S->>S: 验证未登录
S-->>-B: 展示登陆form
B->>+S: POST 用户名 密码
S->>S: 验证用户名和密码成功
S->>S: 创建全局会话
S->>S: 创建ticket
S-->>-B: 302重定向<br>set cookie: ssoid=1234, sso.com<br>redirect: a.com/pageA?ticket=T123
  1. 用户访问网站a.com下的pageA页面
  2. 由于没有登录,则会重定向到认证中心,并带上回调地址sso.com?redirect=a.com/pageA,以便用户登录之后能跳转回来
  3. 用户在认证中心输入账号密码,提交登录。
  4. 认证中心验证账号密码有效,然后重定向到a.com/pageA?ticket=T123并带上授权码ticket,并将认证中心sso.com的登录态写入Cookie。
  5. 在a.com的服务器中,拿着ticket向认证中心确认,授权码ticket真实有效。
  6. ticket验证成功后,a.com将登录信息写入自己域名下的cookie中。

用户访问接入了认证中心的其它服务时:

sequenceDiagram
participant B as 浏览器
participant C as 系统B(b.com)
participant S as 认证中心(sso.com)

B->>+C: 访问系统B的受保护资源<br>b.com/pageB
C->>C: 验证未登录
C-->>-B: 重定向到认证中心<br>sso.com/login?redirect=b.com/pageB
B->>+S: 访问sso.com<br>sso.com/login?redirect=b.com/pageB<br>cookie: ssoid=1234
S->>S: 有cookie,用户已登录
S-->>-B: 重定向到b.com/pageB?ticket=T456

认证中心发现自己的域名下已经有了cookie,说明之前用户已经有效登录过了,所以直接将新的ticket带到b.com,b.com拿该ticket验证用户信息后种下自己的cookie

该方案需要确保所有的服务都在同一父域名下,如a.baidu.com, b.baidu.com, c.d.baidu.com等,由于任一子服务可以将cookie种到baidu.com域名下,所以一个服务登录之后,只需要各子服务器能够共享登录态,其它服务就不需要再次登录了。

sequenceDiagram
participant Browser as 浏览器
participant A as a.baidu.com
participant B as b.baidu.com

Browser->>+A: 用户访问a.baidu.com受保护页面
A->>A: 未登录
A-->>-Browser: 返回登录form
Browser->>+A: post 用户名密码登录
A->>A: 验证成功<br>session写入redis, 与b.baidu.com, c.d.baidu.com共享
A-->>-Browser: 种入baidu.com域的cookie<br>Set-Cookie: name=value#59; domain=baidu.com
Browser->>+B: 访问b.baidu.com受保护页面
B->>B: 浏览器将baidu.com的cookie传递到b.baidu.com<br>检查cookie有效
B-->>-Browser: 返回b.baidu.com受保护页面

登录服务也可以用一个专门的服务提供,如oa.baidu.com,这样不需要每个子域服务都开发登录功能。

评论列表:

暂无评论 😭