详述单点登录(SSO)

一、SSO核心准备

在讲流程前,先明确核心角色和基础约束,这是理解流程的关键:

1. 核心角色
角色 职责 举例
用户(User) 访问各个业务系统,需要完成身份认证的终端使用者 员工、普通用户
IdP(身份提供商) 统一的身份认证中心,负责验证用户身份、颁发认证凭证(token)、管理全局会话 企业登录中心、微信开放平台、OAuth2.0授权服务器
SP(服务提供商) 依赖IdP完成认证的业务系统,信任IdP颁发的凭证,为用户提供具体服务 企业OA、CRM、报销系统、电商子站
2. 技术前提(保障流程安全/可行)
  • 通信协议:所有交互必须基于HTTPS(防止token/账号密码被中间人窃取);
  • 域名策略
    • 同域场景:IdP和所有SP属于同一主域名(如idp.company.comoa.company.comcrm.company.com),Cookie可跨子域共享,流程更简单;
    • 跨域场景:IdP和SP域名不同(如idp.comsp1.comsp2.com),需通过URL重定向、PostMessage或第三方Cookie(需浏览器允许)完成凭证传递;
  • 凭证类型 :IdP通常颁发两种token(兼顾安全和易用):
    • access_token(访问令牌):短期有效(1小时内),供SP验证用户身份;
    • refresh_token(刷新令牌):长期有效(7天),用于过期后刷新access_token,通常存储在IdP的HttpOnly Cookie中。

场景1:用户首次访问某SP(如OA系统)的完整登录流程(核心)

这是SSO的基础流程,所有后续免登都依赖这次认证:

步骤 执行主体 具体动作(技术细节) 核心目的
1 用户 → SP1服务器 用户在浏览器输入OA地址(https://oa.company.com),发起HTTP请求 访问目标业务系统
2 SP1服务器 1. 检测到SP1本地无用户会话(无Cookie/sessionid); 2. 生成唯一state参数(防CSRF攻击); 3. 返回302重定向响应,跳转到IdP登录页:https://idp.company.com/login?redirect_uri=https://oa.company.com/callback&state=xxx 引导用户到统一登录中心
3 IdP服务器 1. 检测到IdP无全局会话(浏览器Cookie中无IdP的sessionid); 2. 返回IdP登录页面(账号密码表单) 要求用户完成身份验证
4 用户 → IdP服务器 输入账号密码,提交登录表单(HTTPS POST请求) 提交身份凭证
5 IdP服务器 1. 验证账号密码(对比数据库/LDAP); 2. 验证通过:生成IdP全局会话(sessionid),通过Set-Cookie存入浏览器(设置HttpOnly+Secure+SameSite=Strict); 3. 生成access_token(JWT格式,含用户ID/权限,私钥签名)和refresh_token 完成身份认证,生成全局凭证
6 IdP服务器 返回302重定向响应,跳转到SP1的回调地址,并携带参数:https://oa.company.com/callback?token=xxx&state=xxx 把token传递给SP1
7 SP1服务器 1. 验证state参数(和步骤2生成的一致,防CSRF); 2. 向IdP发起验证请求:https://idp.company.com/verify_token?token=xxx; 3. 等待IdP返回验证结果 确认token是IdP颁发且未篡改
8 IdP服务器 1. 校验token的签名(用公钥验证)、有效期、用户状态; 2. 返回验证结果(合法,附带用户基础信息) 确认token合法性
9 SP1服务器 1. 验证通过:创建SP1本地会话(生成SP1的sessionid,存入Cookie); 2. 返回OA系统页面(用户已登录状态) 完成SP1的登录,允许访问

场景2:用户已登录IdP,访问其他SP(如CRM系统)的免登流程

这是SSO的核心价值------一次登录,多系统通行:

步骤 执行主体 具体动作(技术细节) 核心目的
10 用户 → SP2服务器 输入CRM地址(https://crm.company.com),发起HTTP请求 访问第二个业务系统
11 SP2服务器 1. 检测到SP2无本地会话; 2. 生成state参数; 3. 重定向到IdP:https://idp.company.com/login?redirect_uri=https://crm.company.com/callback&state=yyy 引导到IdP验证是否已登录
12 IdP服务器 1. 检测到浏览器Cookie中携带IdP的sessionid(全局会话有效); 2. 无需展示登录页,直接生成新的access_token(针对SP2) 识别用户已登录,免登
13 IdP服务器 重定向到SP2的回调地址,携带token=zzz&state=yyy 传递token给SP2
14 SP2服务器 验证state,并向IdP发起verify_token请求 验证token合法性
15 IdP服务器 返回token验证结果(合法) 确认身份
16 SP2服务器 创建SP2本地会话,返回CRM系统页面(已登录状态) 完成SP2免登,允许访问

场景3:全局登出流程(所有SP同步登出)

SSO不仅要"一次登录",还要"一次登出",确保所有系统同步退出:

步骤 执行主体 具体动作(技术细节) 核心目的
17 用户 → SP1服务器 在OA系统点击"退出登录"按钮,发起登出请求 触发全局登出
18 SP1服务器 1. 清除SP1本地会话(删除SP1的sessionid Cookie); 2. 重定向到IdP的全局登出接口:https://idp.company.com/logout?redirect_uri=https://company.com/logout_success 通知IdP执行全局登出
19 IdP服务器 1. 清除IdP全局会话(删除IdP的sessionid Cookie); 2. 遍历所有已登录的SP(IdP记录了用户登录过的SP列表),调用各SP的登出接口(如https://oa.company.com/logouthttps://crm.company.com/logout 终止全局会话,通知所有SP登出
20 所有SP服务器 接收到IdP的登出通知,清除各自的本地会话 同步退出所有系统
21 IdP服务器 重定向到统一的"登出成功"页面 完成全局登出

三、关键技术细节补充(避免流程漏洞)

  1. token的安全性保障
    • access_token必须用非对称加密(如RS256)签名:IdP用私钥签名,SP用公钥验证,防止token被篡改;
    • access_token有效期要短(1小时内),即使被盗,攻击窗口小;
    • refresh_token存储在IdP的HttpOnly Cookie中,禁止JS读取,防XSS攻击。
  2. 跨域场景的适配
    • 若IdP和SP域名不同(如idp.comsp1.com),无法通过Cookie共享会话,可采用「OAuth2.0授权码模式」:IdP先返回code(授权码),SP再用code向IdP换取token,避免token暴露在URL中;
    • 或用「PostMessage」实现跨域通信,SP嵌入IdP的登录弹窗,登录成功后通过PostMessage传递token。
  3. 会话超时处理
    • IdP的全局会话设置超时时间(如2小时无操作),超时后自动失效,用户访问新SP时需重新登录;
    • SP的本地会话超时时间建议和IdP一致,避免SP会话有效但IdP会话失效的情况。

总结

  1. 核心逻辑:SSO的本质是「IdP统一管理身份认证,SP信任IdP颁发的token」,首次登录完成IdP全局会话创建,后续SP通过验证token实现免登;
  2. 关键步骤:首次登录的核心是"SP重定向→IdP认证→token回传→SP验证",免登的核心是"IdP识别全局会话→直接发token",登出的核心是"清除IdP全局会话+通知所有SP清本地会话";
  3. 安全关键:全程HTTPS、token短有效期+非对称签名、Cookie加HttpOnly/Secure/SameSite、state参数防CSRF。

关键点回顾:

  • SSO的核心是IdP的「全局会话」和给SP颁发的「token凭证」;
  • 免登的前提是IdP能识别用户的全局会话(通过Cookie中的sessionid);
  • 全局登出需同步清除IdP全局会话和所有SP的本地会话。
相关推荐
灵感__idea19 小时前
Hello 算法:以“快”著称的哈希
前端·javascript·算法
恋猫de小郭19 小时前
Flutter 官方正式解决 WebView 在 iOS 26 上有点击问题
android·前端·flutter
阿珊和她的猫20 小时前
CSS3新特性概述
前端·css·css3
前端小端长21 小时前
qiankun 微前端应用入门教程:从搭建到部署
前端
yinuo1 天前
前端跨页面通讯终极指南⑥:SharedWorker 用法全解析
前端
PineappleCoder1 天前
还在重复下载资源?HTTP 缓存让二次访问 “零请求”,用户体验翻倍
前端·性能优化
拉不动的猪1 天前
webpack编译中为什么不建议load替换ast中节点删除consolg.log
前端·javascript·webpack
李姆斯1 天前
Agent时代下,ToB前端的UI和交互会往哪走?
前端·agent·交互设计
源码获取_wx:Fegn08951 天前
基于springboot + vue健身房管理系统
java·开发语言·前端·vue.js·spring boot·后端·spring