传统登录
提到单点登录,首先可以想到传统登录,通过登录页面根据用户名查询用户信息,判断密码是否正确,正确则将用户信息写到session,访问的时候通过从session中获取用户信息,判断是否已登录,登录则允许访问。
传统登录流程图

传统登录流程说明
-
步骤1-3:用户主动提交凭证
-
步骤4-7:服务端密码验证(需数据库查询)
-
步骤8:会话创建(核心差异点:每个系统独立维护Session)
-
步骤11-14:后续访问通过SessionID验证
传统登录的缺点
由于session不能共享,服务越来越多,并且还服务还搭建集群,导致每访问另外一个服务都需要重新登录
与单点登录SSO的关键区别
| 特性 | 传统登录 | 单点登录(SSO) |
|---|---|---|
| 认证范围 | 单系统内有效 | 所有信任同一IDP的系统通用 |
| 会话存储 | 各系统独立存储Session | 集中存储在身份提供者(IDP) |
| 用户体验 | 每个系统需单独登录 | 一次登录,多系统通行 |
| 密码验证次数 | 每次登录都验证 | 仅在IDP验证一次 |
| 跨域支持 | 需要额外处理(如共享Session) | 原生支持跨域 |
单点登录
单点登录概念
单点登录(Single Sign-On,简称SSO)是一种身份验证机制,允许用户使用一组凭证(如用户名和密码)登录到多个相关但独立的软件系统中。
在前端开发中,实现单点登录可以极大地提升用户体验,因为用户无需为每个系统单独登录,从而减少了重复输入凭证的麻烦。
单点登录的工作原理
1. 用户访问应用:用户尝试访问需要身份验证的应用A。
2. 重定向到身份提供者:如果用户尚未登录,应用A会将用户重定向到身份提供者(Identity Provider, IDP)。这个身份提供者可以是企业内部的认证服务,也可以是第三方服务,如Google、Facebook等。
3. 用户登录:用户在身份提供者的登录页面输入凭证进行登录。
4. 身份验证:身份提供者验证用户凭证。如果凭证正确,身份提供者会生成一个身份验证令牌(如JWT)。
5. 重定向回应用:身份提供者将用户重定向回应用A,并附带身份验证令牌。
6. 应用验证令牌:应用A接收令牌,并向身份提供者验证令牌的有效性。
7. 访问资源:如果令牌有效,应用A允许用户访问受保护的资源。
8. 跨应用访问:当用户尝试访问另一个应用B时,如果应用B和应用A属于同一个SSO系统,应用B会检查用户是否已经通过身份提供者进行了身份验证。如果已经验证,用户可以直接访问应用B,无需再次输入凭证。
单点登录的关键技术
这里只简单梳理一下,详细的见文章最后的补充;
Cookie
在传统的Web应用中,Cookie是实现会话管理的主要方式。当用户成功登录后,服务器会设置一个Cookie,前端通过这个Cookie来维持用户的登录状态。
在SSO中,这个Cookie通常由身份提供者设置,所有参与SSO的应用都可以读取这个Cookie来判断用户是否已经登录。
JSON Web Tokens (JWT)
JWT是一种开放标准(RFC 7519),用于在各方之间安全地传输信息。在SSO中,身份提供者生成的令牌通常是一个JWT,前端应用可以将这个JWT存储在本地存储(如localStorage或sessionStorage)中,或者作为Cookie的一部分。
当用户访问其他应用时,前端应用会将JWT发送给服务器,服务器验证JWT的有效性,从而决定是否允许用户访问。
OAuth 2.0
OAuth 2.0是一个授权框架,广泛用于实现SSO。通过OAuth 2.0,应用可以请求用户授权访问其在其他服务上的数据,而无需直接处理用户的凭证。
在SSO场景中,OAuth 2.0可以用于用户登录和授权。
OpenID Connect
OpenID Connect是基于OAuth 2.0的简单身份层,它允许客户端根据授权服务器的认证结果验证最终用户的身份,并获取基本的用户信息。
OpenID Connect是实现SSO的常用协议之一。
OIDC = OAuth 2.0 + 身份认证;
单点登录的注意事项
安全性:确保令牌的安全传输和存储,避免令牌泄露。使用HTTPS协议来加密通信,确保数据在传输过程中的安全。
用户体验:设计良好的用户体验,确保用户在不同应用之间切换时感觉流畅,减少登录的繁琐步骤。
跨域问题:在实现SSO时,可能会遇到跨域问题,特别是在使用Cookie时。需要确保Cookie的设置和读取符合跨域策略。
会话管理:合理管理用户的会话,包括会话的创建、维护和销毁,确保会话的安全性和有效性。
通过上述技术和注意事项,前端开发者可以有效地实现单点登录,提升用户体验,同时确保系统的安全性和可靠性。
前端实现单点登录(SSO)
单点登录它是一个功能可以控制多个有联系的系统操作,简单地理解为通过单点登录可以让用户只需要登录一次软件或者系统,那么同系统下的平台都可以免去再次注册、验证、访问权限的麻烦程序,通俗易懂的理解为一次性登录也可以一次性下线。
单点登录的核心思想是:用户登录后,认证信息会在多个系统之间共享,用户只需登录一次,就可以访问所有系统。
单点登录使用场景
1、一个系统登录流程
用户进入系统——未登录——跳转登录界面——用户名和密码发送——服务器端验证后,设置一个cookie发送到浏览器,设置一个session存放在服务器——用户再次请求(带上cookie)——服务器验证cookie和session匹配后,就可以进行业务了。
2、多个系统登录
如果一个大公司有很多系统,a.seafile.com, b.seafile.com,c.seafile.com。这些系统都需要登录,如果用户在不同系统间登录需要多次输入密码,用户体验很不好;
所以使用 SSO (single sign on) 单点登录实现。
3、相同域名,不同子域名下的单点登录
在浏览器端,根据同源策略,不同子域名的cookie不能共享,所以设置SSO的域名为根域名。
SSO登录验证后,子域名可以访问根域名的 cookie,即可完成校验。
在服务器端,可以设置多个子域名session共享(Spring-session)
4、不同域名下的单点登录
CAS流程:用户登录子系统时未登录,跳转到 SSO 登录界面,成功登录后,SSO 生成一个 ST (service ticket )。
用户登录不同的域名时,都会跳转到 SSO,然后 SSO 带着 ST 返回到不同的子域名,子域名中发出请求验证 ST 的正确性(防止篡改请求)。
验证通过后即可完成不同的业务。
单点登录需求
在项目初期,公司中使用的系统很少,通常一个或者两个,每个系统都有自己的登录系统,用户用自己的账号登录,很方便。
但随着公司的不断发展,用到的系统随之增多,用户在操作不同的系统时,需要多次登录,而且每个系统的账号都不一样,这对于用户来说,是很不好的体验。于是,就想到是不是可以在一个系统登录,其他系统就不用登录了呢?这就是单点登录要解决的问题

如图所示,图中有4个系统,分别是Application1、Application2、Application3、和SSO。Application1、Application2、Application3没有登录模块,而SSO只有登录模块,没有其他的业务模块,当Application1、Application2、Application3需要登录时,将跳到SSO系统,SSO系统完成登录,其他的应用系统也就随之登录了。这完全符合我们对单点登录(SSO)的定义。
SSO 机制实现流程
用户首次访问时,需要在认证中心登录:
用户访问网站 a.com 下的 pageA 页面。
-
由于没有登录,则会重定向到认证中心,并带上回调地址 (http://www.sso.com?return_uri=a.com/pageA%EF%BC%8C%E4%BB%A5%E4%BE%BF%E7%99%BB%E5%BD%95%E5%90%8E%E7%9B%B4%E6%8E%A5%E8%BF%9B%E5%85%A5%E5%AF%B9%E5%BA%94%E9%A1%B5%E9%9D%A2%E3%80%82 )
-
用户在认证中心输入账号密码,提交登录。
-
认证中心验证账号密码有效,然后重定向 a.com?ticket=123 带上授权码 ticket,并将认证中心 sso.com 的登录态写入 Cookie。
-
在 a.com 服务器中,拿着 ticket 向认证中心确认,授权码 ticket 真实有效。
-
验证成功后,服务器将登录信息写入 Cookie(此时客户端有 2 个 Cookie 分别存有 a.com 和 sso.com 的登录台)。
认证中心登录完成之后,继续访问 a.com 下的其他页面:
这个时候,由于 a.com 存在已登录的 Cookie 信息,所以服务器端直接认证成功。
如果认证中心登录完成之后,访问 b.com 下的页面:
这个时候,由于认证中心存在之前登录过的 Cookie,所以也不用再次输入账号密码,直接返回第 4 步,下发 ticket 给 b.com 即可。
SSO 机制实现方式
单点登录主要有三种实现方式:
-
父域 Cookie
-
认证中心
-
LocalStorage 跨域
一般情况下,用户的登录状态是记录在 Session 中的,要实现共享登录状态,就要先共享 Session,但是由于不同的应用系统有着不同的域名,尽管 Session 共享了,但是由于 SessionId 是往往保存在浏览器 Cookie 中的,因此存在作用域的限制,无法跨域名传递,也就是说当用户在 a.com 中登录后,Session Id 仅在浏览器访问 a.com 时才会自动在请求头中携带,而当浏览器访问 b.com 时,Session Id 是不会被带过去的。
实现单点登录的关键在于,如何让 Session Id(或 Token)在多个域中共享。
1. 父域 Cookie
Cookie 的作用域由 domain(域名) 属性和 path (域名)属性共同决定。
-
Domain 属性:这个属性指定了Cookie可以被发送到的域名。默认情况下,Cookie只能发送给创建它的那个域名。但是,通过设置
domain属性,你可以控制哪些域名下的请求会包含该Cookie。例如,如果设置domain=example.com,则此Cookie不仅会在对example.com的请求中发送,也会在对sub.example.com这样的子域请求中发送。注意,出于安全考虑,你不能设置一个与当前页面所在域名无关的域作为cookie的有效域。 -
Path 属性:这个属性指定的是Web服务器上的URL路径,它规定了Cookie在哪些路径下有效。只有当访问的URL路径与设置的
path值匹配或者是指定路径的子目录时,浏览器才会附带发送该Cookie。例如,如果你在一个网站的/accounts路径上设置了Cookie,并且指定了path=/accounts,那么这个Cookie只会在对该路径或其子路径(如/accounts/profile)的请求中被发送。对于不在这些路径下的请求(比如/home),这个Cookie不会被发送。
domain决定跨域共享Cookie的能力,而path进一步限制了Cookie在哪个站点路径内有效
domain(域名) 属性的有效值为当前域或其父域的域名/IP地址,在 Tomcat (Apache Tomcat 是一款开源的软件服务器)中,domain(域名)属性默认为当前域的域名/IP地址。 path (域名)属性的有效值是以“/”开头的路径,在 Tomcat 中, path (域名)属性默认为当前 Web 应用的上下文路径。
如果将 Cookie 的 domain 属性设置为当前域的父域,那么就认为它是父域 Cookie。Cookie 有一个特点,即父域中的 Cookie 被子域所共享,也就是说,子域会自动继承父域中的 Cookie。
利用 Cookie 的这个特点,可以将 Session Id(或 Token)保存到父域中就可以了。我们只需要将 Cookie 的 domain(域名)属性设置为父域的域名(主域名),同时将 Cookie 的 path (域名)属性设置为根路径,这样所有的子域应用就都可以访问到这个 Cookie 了。不过这要求应用系统的域名需建立在一个共同的主域名之下,如 tieba.baidu.com 和 map.baidu.com,它们都建立在 baidu.com 这个主域名之下,那么它们就可以通过这种方式来实现单点登录。
总结:此种实现方式比较简单,但不支持跨主域名。
2. 认证中心
我们可以部署一个认证中心,认证中心就是一个专门负责处理登录请求的独立的 Web 服务。
用户统一在认证中心进行登录,登录成功后,认证中心记录用户的登录状态,并将 Token 写入 Cookie。(注意这个 Cookie 是认证中心的,应用系统是访问不到的)
应用系统检查当前请求有没有 Token,如果没有,说明用户在当前系统中尚未登录,那么就将页面跳转至认证中心进行登录。由于这个操作会将认证中心的 Cookie 自动带过去,因此,认证中心能够根据 Cookie 知道用户是否已经登录过了。如果认证中心发现用户尚未登录,则返回登录页面,等待用户登录,如果发现用户已经登录过了,就不会让用户再次登录了,而是会跳转回目标 URL ,并在跳转前生成一个 Token,拼接在目标 URL 的后面,回传给目标应用系统。
应用系统拿到 Token 之后,还需要向认证中心确认下 Token 的合法性,防止用户伪造。确认无误后,应用系统记录用户的登录状态,并将 Token 写入 Cookie,然后给本次访问放行。(这个 Cookie 是当前应用系统的,其他应用系统是访问不到的)当用户再次访问当前应用系统时,就会自动带上这个 Token,应用系统验证 Token 发现用户已登录,于是就不会有认证中心什么事了。
总结:此种实现方式相对复杂,支持跨域,扩展性好,是单点登录的标准做法。
3. LocalStorage 跨域
单点登录的关键在于,如何让 Session Id(或 Token)在多个域中共享。但是 Cookie 是不支持跨主域名的,而且浏览器对 Cookie 的跨域限制越来越严格。
在前后端分离的情况下,完全可以不使用 Cookie,我们可以选择将 Session Id (或 Token )保存到浏览器的 LocalStorage 中,让前端在每次向后端发送请求时,主动将 LocalStorage 的数据传递给服务端。这些都是由前端来控制的,后端需要做的仅仅是在用户登录成功后,将 Session Id (或 Token )放在响应体中传递给前端。
在这样的场景下,单点登录完全可以在前端实现。前端拿到 Session Id (或 Token )后,除了将它写入自己的 LocalStorage 中之外,还可以通过特殊手段将它写入多个其他域下的 LocalStorage 中。
总结:此种实现方式完全由前端控制,几乎不需要后端参与,同样支持跨域。
SSO 单点登录退出
目前我们已经完成了单点登录,在同一套认证中心的管理下,多个产品可以共享登录态。现在我们需要考虑退出了,即:在一个产品中退出了登录,怎么让其他的产品也都退出登录?
原理其实不难,可以在每一个产品在向认证中心验证 ticket(token) 时,其实可以顺带将自己的退出登录 api 发送到认证中心。
当某个产品 c.com 退出登录时:
清空 c.com 中的登录态 Cookie。请求认证中心 sso.com 中的退出 api。认证中心遍历下发过 ticket(token) 的所有产品,并调用对应的退出 api,完成退出;
补充Session ID、Token 和 Cookie
Session ID
-
概念:服务器生成的唯一标识符,用于关联服务器端存储的用户会话数据
-
使用场景:
-
传统基于会话的用户认证
-
需要服务器端状态管理的应用
-
敏感数据存储在服务端的场景
-
-
典型流程:

Token(如 JWT)
-
概念:自包含的验证令牌,通常采用JSON Web Token格式
-
使用场景:
-
无状态分布式系统
-
跨域/跨服务认证(微服务架构)
-
移动APP认证
-
前后端分离应用
-
-
典型流程:

Cookie
-
概念:浏览器存储的小型数据片段(键值对)
-
使用场景:
-
会话状态管理
-
用户偏好设置存储
-
跨请求保持状态
-
实现"记住我"功能
-
-
关键属性:
Set-Cookie: sessionid=abc123; HttpOnly; // 防XSS Secure; // 仅HTTPS SameSite=Lax; // 防CSRF Max-Age=3600
组合使用最佳实践
现代Web应用常见组合方案:
安全建议:
-
敏感操作使用短过期时间的Session ID
-
JWT设置合理过期时间(access_token: 15-30min, refresh_token: 7d)
-
Cookie必须设置:
Set-Cookie: token=xxx; HttpOnly; Secure; SameSite=Strict; Path=/; -
JWT需验证签名算法防止算法替换攻击
三者关键区别
| 特性 | Session ID | Token (JWT) | Cookie |
|---|---|---|---|
| 存储位置 | 服务器内存/数据库 | 客户端存储 | 浏览器存储 |
| 数据内容 | 无意义随机字符串 | 包含用户数据+签名 | 键值对数据 |
| 状态管理 | 有状态(服务器存储会话) | 无状态(自包含验证) | 传输载体 |
| 安全性 | 依赖HTTPS+HttpOnly | 依赖签名算法+HTTPS | 需Secure+HttpOnly |
| 跨域支持 | 需配置CORS+SameSite | 原生支持跨域 | 受SameSite策略限制 |
| 生命周期 | 服务端可控(随时失效) | 依赖过期时间(exp claim) | 可设Max-Age/会话级 |
| 典型大小 | 小(通常<1KB) | 中(通常2-10KB) | 小(单个<4KB, 域名限50) |
| 访问方式 | 浏览器自动携带 | 需手动添加Authorization头 | 浏览器自动携带 |
核心区别
-
Session ID:服务器会话的"钥匙串"(数据存在服务器)
-
Token:自包含的"电子通行证"(数据在令牌本身)
-
Cookie:浏览器的"便签本"(存储键值对数据)
补充OAuth 2.0
现实场景:美食点评APP想访问你的微信运动数据
假设你安装了一个「美食点评APP」,它想帮你推荐附近的餐厅。为了更精准推荐,它说:"我可以看看你微信运动的步数数据吗?这样能判断你是喜欢步行还是开车找餐厅。"
这就是典型的 OAuth 2.0 应用场景:
一个应用(美食APP)想访问你在另一个服务(微信)的受保护资源(运动数据),但你不愿意把微信账号密码直接给它;
OAuth 2.0 如何解决?(授权码模式流程)
OAuth 2.0关键角色解析
| 角色 | 本例中 | 作用 |
|---|---|---|
| 资源所有者 | 用户 | 决定是否授权 |
| 客户端 | 美食APP | 想访问数据的应用 |
| 授权服务器 | 微信认证服务 | 管理用户授权的服务器 |
| 资源服务器 | 微信运动API | 存储数据的服务器 |
OAuth 2.0为什么安全?
-
用户密码不暴露
美食APP全程不知道你的微信密码 -
有限权限控制
你只授权了「读取运动数据」,美食APP无法删除你好友 -
令牌有时效
访问令牌(access_token)通常1-2小时过期 -
可随时撤销
在微信设置里可随时取消美食APP的权限
生活化比喻: 把OAuth想象成酒店房卡:
-
你(资源所有者)在前台(授权服务器)登记
-
前台给你一张房卡(访问令牌)
-
用房卡只能进自己房间(特定权限)
-
退房时卡失效(令牌过期)
-
酒店服务员(客户端)不需要知道你的身份证密码!
OAuth 2.0实际应用场景
-
网站「用微信/微博登录」按钮
-
云笔记APP请求访问微信云存储
-
数据分析工具请求读取Google Analytics数据
-
智能家居APP控制小米设备
OpenID Connect补充
OIDC = OAuth 2.0 + 身份认证
如果说 OAuth 2.0 解决的是「应用能不能访问你的数据」,那么 OIDC 解决的是「应用如何知道你是谁
现实场景:用微信登录知乎
当你在知乎点击「微信登录」时:
-
知乎不需要你的微信密码
-
但知乎需要确认你的真实身份
-
同时想获取你的微信头像和昵称
这就是 OIDC 的典型场景:在授权的同时完成身份认证。
OIDC 核心流程(授权码模式)
核心创新:ID Token
这是 OIDC 的灵魂,一个包含用户身份信息的 JWT:
// 解码后的 ID Token 示例
{
"iss": "https://open.weixin.qq.com/", // 签发者
"sub": "user_123456", // 用户唯一标识
"aud": "zhihu_client_id", // 受众(知乎)
"exp": 1735689600, // 过期时间
"iat": 1735686000, // 签发时间
"name": "张三",
"picture": "https://avatar.jpg",
"email": "zhangsan@example.com"
}
验证过程:
知乎用微信的公钥验证签名 → 检查 aud 是否匹配自己 → 确认 exp 未过期
与 OAuth 2.0 的关键区别
| 特性 | OAuth 2.0 | OpenID Connect (OIDC) |
|---|---|---|
| 主要目的 | 授权访问资源 | 身份认证 + 获取用户信息 |
| 核心凭证 | Access Token | ID Token (JWT) |
| 用户信息获取 | 需额外调用UserInfo接口 | ID Token直接包含基础信息 |
| Scope要求 | 无固定要求 | 必须包含 openid scope |
| 标准化声明 | 无 | 定义标准用户字段 (sub, name, email等) |
OIDC 三大核心组件
ID Token
-
包含用户身份的 JWT
-
示例:
eyJhbGci...(可通过jwt.io解码)
UserInfo Endpoint
-
获取完整用户信息的 API
-
调用方式:
GET /userinfo Authorization: Bearer <access_token>
Discovery Document
-
自动配置的元数据端点
-
例如微信的:
https://open.weixin.qq.com/.well-known/openid-configuration -
包含所有端点地址、支持的算法等
OIDC前端开发必知要点
前端只需处理两种重定向:
// 启动认证
location.href = `https://open.weixin.qq.com/authorize?
client_id=ZHIHU_CLIENT_ID
&redirect_uri=https://zhihu.com/callback
&response_type=code
&scope=openid%20profile
&state=random_string_123`;
// 处理回调
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
const state = urlParams.get('state');
安全注意事项:
-
必须验证
state参数防 CSRF -
永远不要在前端处理 access_token
-
ID Token 验证必须由后端完成
-
使用 PKCE 增强移动端安全
OIDC实际应用场景
-
网站「用微信/Google登录」按钮
-
企业员工单点登录(SSO)系统
-
移动APP的用户身份认证
-
跨平台用户信息同步

6847

被折叠的 条评论
为什么被折叠?



