单点登录(SSO)全景指南:从原理剖析到落地实战

单点登录(SSO)全景指南:从原理剖析到落地实战

在现代企业架构中,微服务、SaaS 应用和内部系统层出不穷。用户往往需要记住十几套账号密码,每访问一个新系统就要重新登录一次。这不仅用户体验极差,也增加了运维管理的成本和安全风险。

单点登录(Single Sign-On, SSO) 正是为了解决这一痛点而生。它的核心理念是:"一次登录,全网通行"

本文将深入拆解 SSO 的核心原理,对比主流协议(CAS、OAuth2、OIDC、SAML),并提供一套可落地的架构设计方案。


一、什么是单点登录(SSO)?

1. 核心定义

SSO 是一种身份认证方案,允许用户使用一套凭证(用户名/密码、生物特征等)登录一个中心化的认证系统后,即可访问所有互相信任的应用系统,而无需再次输入凭证。

2. 传统会话 vs. SSO 会话

  • 传统模式
    • 系统 A 有独立的 Session/Cookie。
    • 系统 B 有独立的 Session/Cookie。
    • 用户访问 A 需登录,访问 B 需再次登录。
    • 缺点:体验割裂,密码管理混乱,注销困难(需分别退出)。
  • SSO 模式
    • 存在一个统一的认证中心(Identity Provider, IdP)
    • 所有业务系统(Service Provider, SP)信任该认证中心。
    • 用户只需在认证中心登录一次,访问任何 SP 时,SP 会向认证中心确认用户身份,自动完成登录。

二、核心原理:SSO 是如何工作的?

无论采用哪种协议,SSO 的底层逻辑都依赖于**"票据(Ticket/Token)"**的传递和验证。最经典的流程如下:

场景模型

  • 用户:浏览器端。
  • 认证中心 (SSO Server):负责统一登录、发证。
  • 应用系统 A/B (Client):受保护的业务系统。
  • 共享域名/重定向机制:用于跨域传递状态。

标准交互流程(以基于重定向的 Token 模式为例)

  1. 用户访问应用 A

    • 用户请求 app-a.com
    • 应用 A 发现本地无有效会话,拦截请求,重定向用户到 sso-server.com/login?redirect=app-a.com
  2. 用户在认证中心登录

    • 用户看到 SSO 服务器的登录页。
    • 输入账号密码,SSO 服务器验证通过。
    • 关键步骤 :SSO 服务器生成一个全局会话(Global Session),并创建一个授权码(Authorization Code)票据(Ticket)
    • SSO 服务器重定向回应用 A:app-a.com/callback?code=xyz123
  3. 应用 A 换取用户信息

    • 应用 A 拿到 code,在后台向 SSO 服务器发起请求:POST /verify?code=xyz123&app_id=A
    • SSO 服务器验证 code 有效性,返回用户信息(如 UserID, Role)和一个访问令牌(Access Token)。
    • 应用 A 建立本地会话(Local Session),允许用户访问。
  4. 用户访问应用 B(免登过程)

    • 用户点击链接访问 app-b.com
    • 应用 B 发现无本地会话,重定向到 sso-server.com/login?redirect=app-b.com
    • 关键点:此时浏览器携带了 SSO 服务器的全局 Cookie(步骤 2 中建立的)。
    • SSO 服务器检测到用户已登录(全局会话有效),无需用户再次输入密码
    • SSO 服务器直接生成新的 code,重定向回 app-b.com/callback?code=abc456
    • 应用 B 拿 code 换 Token,建立本地会话。
    • 结果:用户无感知地进入了系统 B。
  5. 单点注销(SLO)

    • 用户在任一系统点击"退出"。
    • 该系统通知 SSO 服务器销毁全局会话。
    • SSO 服务器遍历所有注册过的子系统,发送回调请求,通知它们销毁本地会话。

三、主流协议与方案选型

实现 SSO 有多种协议,选择哪种取决于你的应用场景(内部系统、互联网开放平台、企业间互联)。

协议/方案 全称 特点 适用场景 复杂度
CAS Central Authentication Service 老牌、简单、基于 Ticket。由耶鲁大学开源。 高校、传统企业内部系统、Java 生态。 ⭐⭐
OAuth 2.0 Open Authorization 授权标准,非认证标准。主要用于第三方资源访问授权。 微信/QQ 登录、API 授权。 ⭐⭐⭐
OIDC OpenID Connect 基于 OAuth 2.0 构建的身份认证层。返回 ID Token (JWT)。 现代互联网应用首选,移动端、前后端分离架构。 ⭐⭐⭐⭐
SAML 2.0 Security Assertion Markup Language 基于 XML,极其严谨复杂,企业级标准。 跨国大企业、政府机构、遗留系统集成。 ⭐⭐⭐⭐⭐
LDAP/AD Lightweight Directory Access Protocol 目录服务协议,常作为 SSO 的后端数据源。 企业内部员工账号统一管理。 ⭐⭐⭐

深度解析:为什么现在推荐 OIDC?

虽然 CAS 很简单,但它在移动端支持和标准化方面略显老旧。SAML 太重且解析 XML 性能较差。 OIDC (OpenID Connect) 是目前业界的事实标准:

  1. 基于 JSON 和 JWT:轻量级,易于解析,适合前后端分离。
  2. 标准化用户信息 :定义了标准的 id_token,包含用户身份信息(UserInfo Endpoint)。
  3. 生态丰富:Keycloak, Auth0, Okta, Spring Security OAuth2 等主流框架均原生支持。
  4. 灵活:支持授权码模式(最安全)、隐式模式(已废弃)、密码模式(不推荐)等。

四、落地实现方案:自研 vs. 集成

方案 A:使用成熟开源产品(强烈推荐)

对于大多数团队,不要重复造轮子。身份安全关乎身家性命,成熟的开源产品经过了全球社区的审计和打磨。

1. Keycloak (RedHat 出品)
  • 特点:功能最全,支持 OIDC, SAML, CAS, LDAP 集成,自带管理控制台,支持社交登录,支持多因素认证(MFA)。
  • 优势:开箱即用,社区活跃,文档丰富。
  • 部署:支持 Docker/K8s 部署。
  • 适用:绝大多数中大型项目。
2. MaxKey / Casdoor
  • MaxKey:国内开源,对中文支持好,符合国内信创标准。
  • Casdoor:Go 语言编写,高性能,UI 美观,易于集成。

实施步骤

  1. 部署 Keycloak 服务。
  2. 在 Keycloak 创建 Realm(租户),配置用户数据库(或对接 LDAP/AD)。
  3. 为每个业务系统创建 Client(客户端),获取 Client-IDSecret
  4. 业务系统引入 SDK(如 spring-boot-starter-oauth2-client),配置 issuer-uri 和 client-id。
  5. 代码层面只需添加 @PreAuthorize 等注解即可保护接口。

方案 B:基于 Spring Security 自研(仅限特殊需求)

如果业务极其特殊,无法使用标准产品,可基于 Spring Security + Redis 自研简易 SSO。

核心组件设计

  1. SSO-Auth-Server
    • 提供 /login 页面。
    • 生成全局 Token (UUID),存入 Redis (key: sso_token:xxx, value: userId, expire: 2h)。
    • 提供 /validate 接口供子系统校验 Token。
  2. 业务子系统 Filter
    • 拦截请求,检查本地 Cookie。
    • 无 Cookie 则重定向至 SSO-Auth-Server。
    • 接收回调,调用 /validate,成功后写入本地 Cookie。

⚠️ 自研风险

  • 容易忽略 CSRF 攻击、重放攻击。
  • 单点注销(SLO)逻辑复杂,容易遗漏。
  • 缺乏审计日志和多因素认证支持。
  • 结论 :除非为了学习或极度受限的环境,否则生产环境不建议自研核心认证逻辑

五、关键挑战与解决方案

浏览器的同源策略限制 Cookie 只能在同域下传输。

  • 解决 :SSO 服务器通常部署在独立域名(如 sso.example.com)。业务系统通过重定向将用户带到该域名下建立全局 Cookie,然后再重定向回业务域名。这是标准 OIDC/CAS 流程天然解决的,不需要前端手动操作 Cookie。

2. 单点注销(SLO)的可靠性

如何确保用户退出后,所有子系统都退出?

  • 前端 iframe 法(传统):SSO 服务器返回一个页面,里面包含所有子系统的注销 iframe 链接。但现代浏览器对第三方 Cookie 和 iframe 限制越来越严,此法逐渐失效。
  • 后端回调法(推荐)
    • 子系统登录时,向 SSO 服务器注册一个"注销回调 URL"。
    • 用户注销时,SSO 服务器遍历注册列表,向后端发起 HTTP 请求通知注销。
    • 难点:需处理网络超时、子系统宕机。通常采用"最终一致性"策略,配合消息队列(MQ)广播注销事件。

3. 性能与高可用

认证中心是所有流量的入口,一旦挂掉,全公司系统瘫痪。

  • 集群部署:SSO 服务必须多实例部署,前置负载均衡(Nginx/SLB)。
  • Session 共享:全局会话数据必须存储在外部缓存(Redis Cluster),不能存在内存中。
  • 异地多活:对于超大规模系统,需考虑认证中心的异地容灾。

4. 安全性加固

  • 强制 HTTPS:所有 Token 传输必须加密。
  • 短效 Token:Access Token 有效期设短(如 15 分钟),配合 Refresh Token 机制。
  • 防重放:授权码(Code)只能使用一次,用完即焚。
  • 审计日志:记录所有登录、注销、授权失败的行为。

六、总结与建议

单点登录(SSO)是现代 IT 架构的基础设施。它不仅仅是方便用户少输几次密码,更是企业统一身份治理、提升安全水位的关键一步。

落地建议路线图

  1. 小型项目/初创期:直接使用云厂商提供的身份服务(如 Auth0, 阿里云 IDaaS),零运维成本。
  2. 中型项目/成长期 :私有化部署 KeycloakCasdoor。利用其成熟的 OIDC 协议对接各业务系统。
  3. 大型国企/复杂遗留系统:可能需要混合模式。核心新系统用 OIDC,老旧 Java 系统用 CAS,Windows 域环境用 AD/LDAP 联邦。此时 Keycloak 也能作为聚合层(Identity Broker)来统一对接。

最后记住 :身份认证是安全链条中最脆弱的一环。不要试图自己发明加密算法或认证流程,站在巨人的肩膀上(使用标准协议和成熟产品),才是最高效、最安全的选择。

相关推荐
逆境不可逃2 小时前
【从零入门23种设计模式21】行为型之空对象模式
java·开发语言·数据库·算法·设计模式·职场和发展
健康平安的活着2 小时前
java中乐观锁+事务在批量导入,批量审批案例的使用
java·开发语言
lxh01132 小时前
重复的DNA序列
开发语言·javascript·ecmascript
froginwe112 小时前
Web 词汇表
开发语言
im_AMBER2 小时前
Leetcode 139 最后一个单词的长度 | 找出字符串中第一个匹配项的下标
开发语言·算法·leetcode
2401_889884662 小时前
嵌入式C++测试框架
开发语言·c++·算法
1104.北光c°2 小时前
我理解的Leaf号段模式:美团分布式ID生成系统
java·开发语言·笔记·分布式·github·leaf
DREW_Smile2 小时前
字符函数和字符串函数2
c语言·开发语言
wjs20242 小时前
CSS 颜色
开发语言