Files
Qiniu/technical/sso.md
T

119 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags: [sso, auth, architecture]
create time: 2026-07-13 10:03
---
# SSO 单点登录
## 概述
想象你在一家公司上班:OA 系统一套账号、Git 一套账号、监控平台一套账号、Wiki 又一套账号。每套都要单独注册、单独登录、单独改密码。密码多了记不住就用同一个,一个泄露全军覆没。
**SSO(Single Sign-On,单点登录)** 就是解决这个问题的:**登录一次,到处通行**。就像你办了一张公司门禁卡,刷卡进大楼之后,食堂、健身房、图书馆都认这张卡,不用每个地方再登记一次。
## 核心角色
在理解 SSO 流程之前,先认识三个核心角色:
| 角色 | 全称 | 一句话解释 | 生活类比 |
|------|------|-----------|----------|
| **User** | End User | 使用系统的你 | 进门的人 |
| **SP** | Service Provider(服务提供方) | 你实际要访问的业务系统 | 食堂、健身房 |
| **IdP** | Identity Provider(身份提供商) | 统一认证中心,负责验证「你是谁」 | 前台门禁系统 |
> [!tip] SP 和 IdP 的关系
> IdP 知道「你是谁」,SP 知道「你能干什么」。SP 不自己验身份,而是**委托** IdP 来做——就像食堂不查你的身份证,它只认门禁卡。
## 核心流程
SSO 的本质是「认证委托」—— SP 把「验证身份」这件事交给 IdP:
```mermaid
sequenceDiagram
participant U as 用户 (浏览器)
participant App as 业务应用 (SP)
participant IdP as 认证中心 (IdP)
U->>App: 1. 访问受保护的页面
App->>U: 2. 「你还没登录,去认证中心吧」<br/>浏览器地址栏变成 IdP 的网址
U->>IdP: 3. 在 IdP 页面输入账号密码
IdP-->>U: 4. 验证通过,给用户一个「凭证」
IdP->>App: 5. 把用户带回 SP,同时带上「凭证」
App->>IdP: 6. SP 后端拿着凭证去 IdP 校验真伪
IdP-->>App: 7. 「凭证是真的,用户是张三」
App-->>U: 8. 登录成功,放行访问
```
> [!info] 浏览器重定向是什么意思?
> 步骤 2 和 5 涉及「浏览器重定向」—— 你的浏览器地址栏会从 `app.example.com` 跳到 `idp.example.com`,登录完再跳回来。这不是后台偷偷发生的,你能看到地址栏在变。
## SSO 的两种实现思路
### 思路一:共享 Cookie(简单但受限)
所有应用都在同一个主域下(如 `oa.company.com`、`git.company.com`),IdP 在 `.company.com` 这个顶级域上写一个 Cookie,所有子域都能读到。
```mermaid
graph LR
A[用户登录 idp.company.com] -->|写入 .company.com Cookie| B[oa.company.com 读取同一 Cookie]
A --> C[git.company.com 读取同一 Cookie]
A --> D[wiki.company.com 读取同一 Cookie]
```
- ✅ 实现简单,不需要复杂的协议
- ❌ 所有应用必须在同一个主域下,跨域就不行了
- ❌ 安全性低,一个子域被攻破可能波及全部
### 思路二:分布式 Token(主流方案)
IdP 登录成功后颁发一个签名的 **Token**(令牌),各个 SP 独立验证这个 Token 的真伪,不需要和 IdP 实时通信。
- ✅ 跨域、跨平台、跨组织无障碍
- ✅ SP 之间互不依赖
- ✅ 支持移动端、SPA 等各种客户端
- ❌ 实现稍复杂,需要用到标准协议(OIDC/SAML 等)
> **这是当前主流方案**,后面介绍的四种协议(CAS、SAML、OAuth 2.0、OIDC)都是基于这种思路。
## 关键概念速查
### Session vs Token
| 维度 | Session-Cookie | Token (JWT) |
|------|---------------|-------------|
| **存在哪** | 服务端(需要内存/数据库存储) | 客户端(浏览器/手机自己存) |
| **怎么验证** | 每次请求带上 Cookie,服务端查表 | Token 自带签名,服务端本地验签即可 |
| **跨域能力** | Cookie 受浏览器同源策略限制,只能同域 | 放在 HTTP Header 里传,没有域限制 |
| **扩展性** | 多个 SP 需要共享 Session Store | 天然无状态,SP 各自验证即可 |
| **怎么注销** | 删掉服务端 Session 就行 | Token 发出去就收不回,靠短过期时间 |
### 什么是 CSRF 攻击?
**CSRF(Cross-Site Request Forgery,跨站请求伪造)**:攻击者诱导你的浏览器向目标网站发请求,浏览器自动带上 Cookie,目标网站以为是你本人操作。
> 类比:有人拿你签过名的空白支票去取钱,银行看到你的签名就放行了。`state` 参数的作用就是在支票上写明「这张支票是给谁用的」,防止被冒领。
### 什么是重放攻击?
攻击者截获了一个有效的请求(比如登录凭证),然后**原样再发一次**,欺骗服务器以为是新的合法请求。
> 类比:你用过的电影票被别人捡到,拿去再刷一次入场。`nonce`(Number used ONCE)参数的作用就是给每张票打上唯一编号,用过就作废。
## 推荐阅读顺序
如果你是第一次接触 SSO,建议按以下顺序阅读:
1. **本文** — 建立整体认知
2. [[sso/sso-oauth2|OAuth 2.0 授权码模式]] — 理解「授权」和「认证」的区别
3. [[sso/sso-oidc|OpenID Connect (OIDC)]] — 在 OAuth 2.0 基础上补齐「认证」
4. [[sso/sso-comparison|协议对比与选型指南]] — 了解全景,学会选型
5. [[sso/sso-saml|SAML 2.0]] / [[sso/sso-cas|CAS 协议]] — 按需阅读,了解企业级和传统方案
## 关联笔记
- [[sso/sso-oauth2|OAuth 2.0 授权码模式]]
- [[sso/sso-oidc|OpenID Connect (OIDC)]]
- [[sso/sso-saml|SAML 2.0]]
- [[sso/sso-cas|CAS 协议]]
- [[sso/sso-comparison|协议对比与选型指南]]