什么是单点登录(SSO)?同域和跨域的 SSO 分别怎么实现?
简化版
单点登录(SSO,Single Sign-On)是「一次登录,多个系统通用」——用户在一个系统登录后,访问同一组织下的其他系统时不用重复登录。实现方式取决于系统是否同域:① 同域 SSO(如 a.example.com、b.example.com)——最简单,把 Cookie 的 domain 设为父域 .example.com,多个子域共享同一个登录 Cookie/Session 即可;② 跨域 SSO(如 example.com、other.com,Cookie 无法共享)——需要一个独立的认证中心(SSO Server):用户在认证中心登录一次,各业务系统通过「重定向到认证中心校验 + 拿票据/token」来确认登录状态,代表方案是 CAS(票据机制)和 基于 OAuth2/OIDC 或 JWT 的方案。核心思路:把「登录」这件事集中到一个认证中心,其他系统信任它的登录结果。
详细版
SSO 的核心诉求:
没有 SSO:用户访问 A 系统登录一次、访问 B 系统又登录一次、C 系统再登录...(重复、烦)
有 SSO:用户登录一次 → A、B、C 系统都认得他,不用重复登录
关键:多个系统"共享"同一份登录状态
同域 vs 跨域 SSO:
| 维度 | 同域 SSO | 跨域 SSO |
|---|---|---|
| 场景 | 子域名(a.x.com、b.x.com) | 不同主域名(x.com、y.com) |
| 能否共享 Cookie | 能(设 Cookie domain=.x.com) | 不能(Cookie 不跨主域) |
| 实现难度 | 简单 | 复杂,需认证中心 |
| 典型方案 | 共享 Cookie / 共享 Session | CAS、OAuth2/OIDC、JWT |
跨域 SSO 的核心:认证中心 + 票据(以 CAS 为例):
1. 用户访问系统A(未登录)→ A 重定向到"认证中心 SSO Server"
2. 用户在认证中心登录(输入用户名密码)→ 认证中心记录登录状态(在认证中心自己的域下种 Cookie)
→ 认证中心生成一个"票据 ticket",重定向回 A(带上 ticket)
3. 系统A 拿 ticket 到认证中心后端校验 → 校验通过,A 确认用户已登录,创建 A 的本地会话
4. 用户再访问系统B(未登录)→ B 重定向到认证中心
→ 认证中心发现用户已登录(自己域下有 Cookie)→ 直接生成新 ticket 重定向回 B(无需再输密码)
5. B 校验 ticket → 确认登录 → 用户无感登录了 B
⚠️ SSO 的关键是「登录状态集中在认证中心,业务系统信任认证中心的结果」。跨域时业务系统之间不能共享 Cookie,所以不能靠 Cookie 传递登录态,而是靠「重定向到认证中心 + 票据/token 校验」。理解「认证中心自己域下有登录 Cookie(所以它知道你登录了),业务系统靠票据向认证中心确认」,就理解了跨域 SSO 的本质。
完整版教学
一、SSO 要解决什么:多系统的重复登录
大公司往往有很多系统——OA、邮箱、财务、CRM…如果每个系统都要单独登录,用户体验极差(记一堆账号、反复登录)。SSO 的目标是「一次登录,全网通行」:
无 SSO 的痛苦:
登录 OA(输密码)→ 切到邮箱(又输密码)→ 切到财务(再输密码)...
用户烦、账号多、管理难
有 SSO:
登录一次 → OA、邮箱、财务、CRM 全都自动认得你
一套账号、一次登录、统一管理
SSO 的核心是让「多个独立的系统共享同一份登录状态」。难点在于——这些系统是独立部署的(不同服务、可能不同域名),怎么让它们「都知道用户已经登录了」?解法的核心思路是:把「登录认证」这件事从各个业务系统里抽出来,集中到一个「认证中心」,其他系统信任认证中心的登录结果。这和微服务把治理下沉到基础设施是同一种思想——把「共性的事」集中处理。理解「SSO = 集中认证 + 系统间信任」,就抓住了它的本质。
二、同域 SSO:共享 Cookie 最简单
如果所有系统在同一个主域名下的不同子域(如 oa.example.com、mail.example.com),SSO 最简单——靠共享 Cookie:
Cookie 的 domain 规则:
设置 Cookie 时把 domain 设为父域 ".example.com"
→ 这个 Cookie 会被所有 *.example.com 的子域共享
同域 SSO 实现:
用户在 oa.example.com 登录 → 服务端种一个 domain=.example.com 的登录 Cookie(如 SESSION/token)
→ 用户访问 mail.example.com 时,浏览器自动带上这个 Cookie
→ mail 系统拿到 Cookie 就知道用户已登录(共享了同一份登录态)
关键是 Cookie 的 domain 设为父域——这样一个子域种的 Cookie,其他子域都能读到。所以同域下多个系统只要「共享同一个登录 Cookie + 共享或能互相识别 Session/token」就实现了 SSO。如果用 Session,还需要多系统共享 Session 存储(如都从同一个 Redis 读 Session);如果用 token(JWT),则各系统都能验证同一个 token 即可。同域 SSO 简单,因为浏览器的 Cookie 天然能在子域间共享——这是它的便利,也是它的局限(只适用于同域)。
三、跨域 SSO 的难点:Cookie 不能跨主域
当系统分布在不同的主域名(如 example.com 和 partner.com,或者 example.com 和 example.net)时,同域的方案就失效了——Cookie 不能跨主域共享:
浏览器安全规则:
example.com 种的 Cookie,partner.com 的请求不会带上(Cookie 按域名隔离)
→ 无法靠"共享 Cookie"传递登录状态
所以跨域 SSO 必须换思路:
不能靠"浏览器自动共享登录态"
→ 改为"每个系统主动去认证中心确认用户登录了没"
→ 靠重定向 + 票据/token 来传递和校验登录状态
这是跨域 SSO 复杂的根源——浏览器不让不同主域共享 Cookie,所以登录状态无法「自动流动」到各系统。解法是引入一个「认证中心」作为「登录状态的唯一权威」,各业务系统通过「重定向到认证中心 + 校验票据」来间接获取登录状态。理解「跨域不能共享 Cookie、所以要靠认证中心中转」,就理解了为什么跨域 SSO 需要 CAS 这类方案。
四、CAS:经典的票据方案
CAS(Central Authentication Service)是经典的跨域 SSO 方案,核心是「认证中心 + 票据(ticket)」。完整走一遍:
首次登录(访问系统A):
1. 用户访问 A(未登录)→ A 重定向到认证中心(CAS Server)
2. 用户在认证中心登录 → 认证中心在【自己的域下】种一个登录 Cookie(TGC,记录"这个浏览器已登录")
→ 生成一个 Service Ticket(ST,一次性、针对A的票据)→ 重定向回 A(URL 带 ST)
3. A 后端拿 ST 到认证中心校验 → 校验通过 → A 创建自己的本地会话 → 用户登录成功
再访问系统B(关键:无需再输密码):
4. 用户访问 B(未登录)→ B 重定向到认证中心
5. 认证中心发现【自己域下的 Cookie(TGC)】→ 知道这个浏览器已经登录过了
→ 直接生成新的 ST(针对B)→ 重定向回 B → B 校验 ST → 用户无感登录 B
CAS 的精髓:登录状态记在认证中心自己的域下(TGC Cookie)——所以认证中心知道「这个浏览器登录了」;业务系统靠一次性票据(ST)向认证中心确认——ST 是认证中心颁发的、业务系统拿去校验的「登录凭证」。第二次访问其他系统时,认证中心凭自己的 Cookie 认出用户已登录,直接发票据、不用再输密码——这就是「单点登录」的效果。ST 一次性、短时效,保证安全。这套「认证中心存登录态 + 票据中转」的机制,是 CAS 跨域 SSO 的核心。
五、基于 Token / OAuth2 的现代 SSO
现代 SSO 更多用 JWT/OAuth2/OIDC 方案,思路和 CAS 类似(认证中心 + 凭证),但用 token 替代票据:
基于 OIDC 的 SSO(现在主流):
认证中心 = OIDC 的授权服务器(Identity Provider,IdP)
用户在 IdP 登录一次 → IdP 给用户签发 ID Token(JWT,证明身份)
各业务系统(作为 OAuth2 客户端)通过授权码流程从 IdP 换取 token
→ 拿 token 确认用户身份,实现 SSO
JWT 自包含的优势:
token 里带着用户信息和签名,业务系统本地验签就能确认登录
→ 不用每次都调认证中心校验(对比 CAS 的 ST 要回认证中心校验)
→ 更适合分布式、跨域场景
现代方案的演进:用「自包含的 JWT token」替代「需要回认证中心校验的票据」。CAS 的 ST 是「不透明的票据」,业务系统拿到要回认证中心校验;而 JWT 是「自包含的令牌」,业务系统本地用公钥验签就能确认(不用回认证中心),性能更好、更适合分布式。OIDC(OAuth2 之上的身份层)标准化了这套流程——认证中心作为 IdP(身份提供者)统一登录,各系统信任它签发的 token。所以现代 SSO 多用「OIDC + JWT」——认证中心统一登录、签发 JWT,各系统验签确认身份。这也把 SSO 和前面学的 OAuth2/OIDC 串起来了。
六、SSO 的登出与安全考量
SSO 好用,但有几个必须处理的问题:
① 单点登出(Single Logout):
一处登出,所有系统都要登出(否则登出了 A,B 还是登录状态,不安全)
→ 认证中心要通知所有已登录的业务系统清除会话(比登录更复杂)
② Token/票据的安全:
票据/token 要防窃取(HTTPS 传输)、防重放(一次性/短时效)、防篡改(签名)
③ 认证中心的高可用:
认证中心是"单点"——它挂了所有系统都没法登录
→ 必须集群部署、高可用(它是 SSO 的命脉)
④ 会话时效一致性:
各系统的会话过期时间要和认证中心协调,避免"认证中心过期了但业务系统还认为登录"
其中单点登出是最容易被忽略又最重要的——SSO 让「一次登录全网通行」,那「一次登出」也应该「全网登出」,否则用户以为登出了、实际其他系统还在登录,是安全隐患。实现单点登出需要认证中心「记录用户在哪些系统登录过」,登出时逐个通知它们清除会话,比登录复杂。另外,认证中心是单点故障点(它挂了全体无法登录),必须高可用集群。理解这些安全和可用性考量,才能完整回答 SSO——它不只是「登录一次」,还要处理登出、安全、高可用。
记忆钩子:「SSO=一次登录多系统通用,核心是集中认证+系统间信任;同域 SSO 靠共享 Cookie(domain 设父域 .x.com)最简单;跨域不能共享 Cookie,靠认证中心+票据(CAS 的 TGC 存登录态+ST 一次性票据)或 OIDC+JWT(自包含 token 本地验签);难点:单点登出、认证中心高可用」。
七、常见误区与追问
- 误区:SSO 就是共享 Cookie。 只有「同域」子系统能靠共享 Cookie(domain 设父域);跨主域 Cookie 不能共享,要靠认证中心 + 票据/token 中转。
- 误区:跨域 SSO 直接把登录 Cookie 传给别的域就行。 浏览器安全规则禁止 Cookie 跨主域共享;必须通过重定向到认证中心 + 校验票据/token 来传递登录状态。
- 误区:SSO 只要解决登录就行。 还要解决单点登出(一处登出全网登出,否则安全隐患)、认证中心高可用(单点故障)、票据安全等,登出往往比登录更复杂。
- 误区:认证中心随便部署一个就行。 它是单点故障点——挂了所有系统都无法登录,必须集群高可用部署,是整个 SSO 体系的命脉。
- 追问:同域 SSO 怎么实现? 把登录 Cookie 的 domain 设为父域(如 .example.com),所有子域共享这个 Cookie/登录态;用 Session 需共享 Session 存储(如同一 Redis),用 JWT 则各系统验证同一 token。
- 追问:CAS 的 TGC 和 ST 分别是什么? TGC(Ticket Granting Cookie)种在认证中心自己域下、记录「这个浏览器已登录」;ST(Service Ticket)是认证中心针对某个业务系统颁发的一次性票据,业务系统拿它回认证中心校验确认登录。
- 追问:现代 SSO 为什么多用 JWT 而非 CAS 票据? JWT 是自包含的(带用户信息+签名),业务系统本地验签就能确认登录、不用每次回认证中心校验,性能更好、更适合分布式/跨域;CAS 的 ST 不透明、每次要回认证中心校验。
八、加强记忆
单点登录(SSO)是「一次登录、多系统通用」,核心思路是把登录集中到一个「认证中心」,其他系统信任它的登录结果。实现看是否同域:① 同域 SSO(子域名如 a.x.com/b.x.com)最简单——共享 Cookie(把 Cookie domain 设为父域 .x.com,子域间自动共享登录态),用 Session 需共享 Session 存储、用 JWT 各系统验同一 token;② 跨域 SSO(不同主域,Cookie 不能共享)复杂——必须靠认证中心 + 票据/token 中转:经典方案 CAS(认证中心自己域下种 TGC Cookie 记录「浏览器已登录」,业务系统靠一次性 ST 票据回认证中心校验;第二次访问别的系统时认证中心凭 TGC 认出已登录、直接发票据、不用再输密码),现代方案 OIDC + JWT(认证中心作 IdP 统一登录、签发自包含 JWT,各系统本地验签确认、不用回认证中心,更适合分布式)。SSO 的难点不只是登录:单点登出(一处登出要全网登出,比登录复杂)、认证中心高可用(单点故障、必须集群)、票据安全(HTTPS+一次性+签名)。一句话「SSO 集中认证+系统信任、同域共享 Cookie、跨域靠认证中心+CAS 票据或 OIDC+JWT、难点是单点登出和认证中心高可用」。