66---
77
88> 本文授权转载自 : https://ken.io/note/sso-design-implement 作者:ken.io
9- >
109
11- ## 一、前言
10+ ## SSO 介绍
1211
13- ### 1、SSO说明
12+ ### 什么是 SSO?
1413
15- SSO英文全称Single Sign On,单点登录。SSO是在多个应用系统中 ,用户只需要登录一次就可以访问所有相互信任的应用系统。https://baike.baidu.com/item/SSO/3451380
14+ SSO 英文全称 Single Sign On,单点登录。SSO 是在多个应用系统中 ,用户只需要登录一次就可以访问所有相互信任的应用系统。https://baike.baidu.com/item/SSO/3451380
1615
1716例如访问在网易账号中心(https://reg.163.com/ )登录之后
1817访问以下站点都是登录状态
@@ -21,17 +20,17 @@ SSO英文全称Single Sign On,单点登录。SSO是在多个应用系统中,
2120- 网易博客 [ https://blog.163.com ] ( https://blog.163.com/ )
2221- 网易花田 [ https://love.163.com ] ( https://love.163.com/ )
2322- 网易考拉 [ https://www.kaola.com ] ( https://www.kaola.com/ )
24- - 网易Lofter [ http://www.lofter.com ] ( http://www.lofter.com/ )
23+ - 网易 Lofter [ http://www.lofter.com ] ( http://www.lofter.com/ )
2524
26- ### 2、单点登录系统的好处
25+ ### SSO 有什么好处?
2726
28271 . ** 用户角度** :用户能够做到一次登录多次使用,无需记录多套用户名和密码,省心。
29282 . ** 系统管理员角度** : 管理员只需维护好一个统一的账号中心就可以了,方便。
30293 . ** 新系统开发角度:** 新系统开发时只需直接对接统一的账号中心即可,简化开发流程,省时。
3130
32- ### 3、设计目标
31+ ##SSO 设计与实现
3332
34- 本篇文章也主要是为了探讨如何设计&实现一个SSO系统
33+ 本篇文章也主要是为了探讨如何设计&实现一个 SSO 系统
3534
3635以下为需要实现的核心功能:
3736
@@ -40,88 +39,85 @@ SSO英文全称Single Sign On,单点登录。SSO是在多个应用系统中,
4039- 支持跨域单点登录
4140- 支持跨域单点登出
4241
43- ##二、SSO设计与实现
42+ ### 核心应用与依赖
4443
45- ### 1、核心应用与依赖
44+ ![ 单点登录(SSO)设计 ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/system-design/security/sso/sso-system.png-kblb.png )
4645
47- ![ 单点登录(SSO)设计] ( https://img.ken.io/blog/sso/sso-system.png-kblb.png )
46+ | 应用/模块/对象 | 说明 |
47+ | ----------------- | ----------------------------------- |
48+ | 前台站点 | 需要登录的站点 |
49+ | SSO 站点-登录 | 提供登录的页面 |
50+ | SSO 站点-登出 | 提供注销登录的入口 |
51+ | SSO 服务-登录 | 提供登录服务 |
52+ | SSO 服务-登录状态 | 提供登录状态校验/登录信息查询的服务 |
53+ | SSO 服务-登出 | 提供用户注销登录的服务 |
54+ | 数据库 | 存储用户账户信息 |
55+ | 缓存 | 存储用户的登录信息,通常使用 Redis |
4856
49- | 应用/模块/对象 | 说明 |
50- | ---------------- | ----------------------------------- |
51- | 前台站点 | 需要登录的站点 |
52- | SSO站点-登录 | 提供登录的页面 |
53- | SSO站点-登出 | 提供注销登录的入口 |
54- | SSO服务-登录 | 提供登录服务 |
55- | SSO服务-登录状态 | 提供登录状态校验/登录信息查询的服务 |
56- | SSO服务-登出 | 提供用户注销登录的服务 |
57- | 数据库 | 存储用户账户信息 |
58- | 缓存 | 存储用户的登录信息,通常使用Redis |
57+ ### 用户登录状态的存储与校验
5958
60- ### 2、用户登录状态的存储与校验
59+ 常见的 Web 框架对于 Session 的实现都是生成一个 SessionId 存储在浏览器 Cookie 中。然后将 Session 内容存储在服务器端内存中,这个 [ ken.io ] ( https://ken.io/ ) 在之前 [ Session 工作原理 ] ( https://ken.io/note/session-principle-skill ) 中也提到过。整体也是借鉴这个思路。
6160
62- 常见的Web框架对于[ Session] ( https://ken.io/note/session-principle-skill ) 的实现都是生成一个SessionId存储在浏览器Cookie中。然后将Session内容存储在服务器端内存中,这个 ken.io 在之前[ Session工作原理] ( https://ken.io/note/session-principle-skill ) 中也提到过。整体也是借鉴这个思路。
63- 用户登录成功之后,生成AuthToken交给客户端保存。如果是浏览器,就保存在Cookie中。如果是手机App就保存在App本地缓存中。本篇主要探讨基于Web站点的SSO。
64- 用户在浏览需要登录的页面时,客户端将AuthToken提交给SSO服务校验登录状态/获取用户登录信息
61+ 用户登录成功之后,生成 AuthToken 交给客户端保存。如果是浏览器,就保存在 Cookie 中。如果是手机 App 就保存在 App 本地缓存中。本篇主要探讨基于 Web 站点的 SSO。
6562
66- 对于登录信息的存储,建议采用Redis,使用Redis集群来存储登录信息,既可以保证高可用,又可以线性扩充。同时也可以让SSO服务满足负载均衡/可伸缩的需求。
63+ 用户在浏览需要登录的页面时,客户端将 AuthToken 提交给 SSO 服务校验登录状态/获取用户登录信息
64+
65+ 对于登录信息的存储,建议采用 Redis,使用 Redis 集群来存储登录信息,既可以保证高可用,又可以线性扩充。同时也可以让 SSO 服务满足负载均衡/可伸缩的需求。
6766
6867| 对象 | 说明 |
6968| --------- | ------------------------------------------------------------ |
70- | AuthToken | 直接使用UUID/GUID即可,如果有验证AuthToken合法性需求,可以将UserName+时间戳加密生成,服务端解密之后验证合法性 |
71- | 登录信息 | 通常是将UserId,UserName缓存起来 |
69+ | AuthToken | 直接使用 UUID/GUID 即可,如果有验证 AuthToken 合法性需求,可以将 UserName+时间戳加密生成,服务端解密之后验证合法性 |
70+ | 登录信息 | 通常是将 UserId,UserName 缓存起来 |
71+
72+ ### 用户登录/登录校验
7273
73- ### 3、用户登录/登录校验
74+ ** 登录时序图 **
7475
75- - 登录时序图
76+ ![ SSO系统设计- 登录时序图] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/system-design/security/sso/sso-login-sequence.png-kbrb.png )
7677
77- ![ SSO系统设计-登录时序图] ( https://img.ken.io/blog/sso/sso-login-sequence.png-kbrb.png )
78+ 按照上图,用户登录后 AuthToken 保存在 Cookie 中。 domain=test.com
79+ 浏览器会将 domain 设置成 .test.com,
7880
79- 按照上图,用户登录后AuthToken保存在Cookie中。 domain=test.com
80- 浏览器会将domain设置成 .test.com,
81- 这样访问所有* .test.com的web站点,都会将AuthToken携带到服务器端。
82- 然后通过SSO服务,完成对用户状态的校验/用户登录信息的获取
81+ 这样访问所有 \* .test.com 的 web 站点,都会将 AuthToken 携带到服务器端。
82+ 然后通过 SSO 服务,完成对用户状态的校验/用户登录信息的获取
8383
84- - 登录信息获取/登录状态校验
84+ ** 登录信息获取/登录状态校验**
8585
86- ![ SSO系统设计-登录信息获取/登录状态校验] ( https://img.ken.io/blog /sso/sso-logincheck-sequence.png-kbrb.png )
86+ ![ SSO系统设计-登录信息获取/登录状态校验] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/system-design/security /sso/sso-logincheck-sequence.png-kbrb.png )
8787
88- ### 4、 用户登出
88+ ### 用户登出
8989
9090用户登出时要做的事情很简单:
9191
92921 . 服务端清除缓存(Redis)中的登录状态
93- 2 . 客户端清除存储的AuthToken
93+ 2 . 客户端清除存储的 AuthToken
9494
95- - 登出时序图
95+ ** 登出时序图**
9696
97- ![ SSO系统设计-用户登出] ( https://img.ken.io/blog /sso/sso-logout-sequence.png-kbrb.png )
97+ ![ SSO系统设计-用户登出] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/system-design/security /sso/sso-logout-sequence.png-kbrb.png )
9898
99- ### 5、 跨域登录、登出
99+ ### 跨域登录、登出
100100
101- 前面提到过,核心思路是客户端存储AuthToken,服务器端通过Redis存储登录信息。由于客户端是将AuthToken存储在Cookie中的 。所以跨域要解决的问题,就是如何解决Cookie的跨域读写问题 。
101+ 前面提到过,核心思路是客户端存储 AuthToken,服务器端通过 Redis 存储登录信息。由于客户端是将 AuthToken 存储在 Cookie 中的 。所以跨域要解决的问题,就是如何解决 Cookie 的跨域读写问题 。
102102
103103解决跨域的核心思路就是:
104104
105- - 登录完成之后通过回调的方式,将AuthToken传递给主域名之外的站点,该站点自行将AuthToken保存在当前域下的Cookie中。
106- - 登出完成之后通过回调的方式,调用非主域名站点的登出页面,完成设置Cookie中的AuthToken过期的操作。
107- - 跨域登录(主域名已登录)
108-
109- ![ SSO系统设计-跨域登录(主域名已登录)] ( https://img.ken.io/blog/sso/sso-crossdomain-login-loggedin-sequence.png-kbrb.png )
110-
111- - 跨域登录(主域名未登录)
105+ - 登录完成之后通过回调的方式,将 AuthToken 传递给主域名之外的站点,该站点自行将 AuthToken 保存在当前域下的 Cookie 中。
106+ - 登出完成之后通过回调的方式,调用非主域名站点的登出页面,完成设置 Cookie 中的 AuthToken 过期的操作。
112107
113- ![ SSO系统设计- 跨域登录(主域名未登录) ] ( https://img.ken.io/blog/sso/sso-crossdomain-login-unlogin-sequence.png-kbrb.png )
108+ ** 跨域登录(主域名已登录) **
114109
115- - 跨域登出
110+ ![ SSO系统设计-跨域登录(主域名已登录) ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/system-design/security/sso/sso-crossdomain-login-loggedin-sequence.png-kbrb.png )
116111
117- ![ SSO系统设计-跨域登出 ] ( https://img.ken.io/blog/sso/sso-crossdomain-logout-sequence.png-kbrb.png )
112+ ** 跨域登录(主域名未登录) **
118113
119- ## 三、备注
114+ ![ SSO系统设计-跨域登录(主域名未登录) ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/system-design/security/sso/sso-crossdomain-login-unlogin-sequence.png-kbrb.png )
120115
121- - 关于方案
116+ ** 跨域登出 **
122117
123- 这次设计方案更多是提供实现思路。如果涉及到APP用户登录等情况,在访问SSO服务时,增加对APP的签名验证就好了。当然,如果有无线网关,验证签名不是问题。
118+ ![ SSO系统设计-跨域登出 ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/system-design/security/sso/sso-crossdomain-logout-sequence.png-kbrb.png )
124119
125- - 关于时序图
120+ ## 说明
126121
127- 时序图中并没有包含所有场景,ken.io只列举了核心/主要场景,另外对于一些不影响理解思路的消息能省就省了。
122+ - 关于方案 :这次设计方案更多是提供实现思路。如果涉及到 APP 用户登录等情况,在访问 SSO 服务时,增加对 APP 的签名验证就好了。当然,如果有无线网关,验证签名不是问题。
123+ - 关于时序图:时序图中并没有包含所有场景,只列举了核心/主要场景,另外对于一些不影响理解思路的消息能省就省了。
0 commit comments