概念:单点登录(Single Sign-On, SSO)主要是在多个系统、多个浏览器或多个标签页之间共享登录状态,保证用户只需登录一次,就能访问多个关联应用,而不需要重复登录。
适用于:同一域名下的多个系统或标签页
方案 | 适用范围 | 共享方式 | 缺点 |
---|---|---|---|
localStorage |
同浏览器、同源 | localStorage 共享 token |
不支持跨浏览器或隐身模式 |
sessionStorage |
仅当前标签页 | sessionStorage |
关闭标签页即失效 |
cookie |
同域、所有浏览器 | 服务器 Set-Cookie |
不能跨域,容量限制 |
BroadcastChannel |
同浏览器、同域 | postMessage 事件广播 |
仅适用于同浏览器 |
适用于:多个子系统,支持不同域名共享登录
方案 | 适用范围 | 共享方式 | 适合场景 |
---|---|---|---|
OAuth 2.0 + JWT | 跨域、多端 | 通过授权服务器获取 token |
第三方登录(微信、GitHub) |
CAS (Central Authentication Service) | 内部系统 | CAS 服务器管理登录态 | 企业内网统一认证 |
SSO + Cookie(SameSite=None + CORS) |
跨子域 | 主域 *.example.com 共享 cookie |
适用于 SaaS 平台 |
SSO + Redis + Session | 跨域 | token 存 Redis,前端查询 |
高并发业务 |
localStorage + BroadcastChannel
(适用于同域)适用于:同一浏览器的多个标签页
实现思路:
登录时,将 token
存入 localStorage
并通知其他标签页
新标签页打开时,自动获取 localStorage
的 token
监听 localStorage
变化,保证 token
实时同步
// 登录时设置 token
localStorage.setItem('token', 'your-token-value')
// 监听 token 变化,保证新打开的页面能同步
window.addEventListener('storage', (event) => {
if (event.key === 'token') {
console.log('新 token:', event.newValue)
}
})
✅ 优点:
实现简单
无需后端支持
适用于同一浏览器、同一域名下的多个系统
❌ 缺点:
不能跨浏览器、跨设备共享
不能跨域名(如 a.com
无法共享 b.com
的 token
)
适用于:跨子域(如 admin.example.com
和 user.example.com
)
实现思路:
后端设置 cookie
,作用域为 *.example.com
前端所有子系统 访问 cookie
共享登录状态
跨域设置 SameSite=None; Secure
res.cookie('token', 'your-token', {
domain: '.example.com', // 设置作用域
path: '/',
httpOnly: true,
secure: true,
sameSite: 'None' // 允许跨域
})
fetch('https://auth.example.com/check-login', {
credentials: 'include' // 允许跨域携带 Cookie
})
.then(res => res.json())
.then(data => {
console.log('登录状态:', data)
})
✅ 优点:
支持多个子域共享登录
安全性较高
用户体验好
❌ 缺点:
不能跨主域(如 example.com
不能共享 other.com
)
需要 HTTPS
浏览器 SameSite
限制较多
适用于:多端、第三方应用、社交登录(如 Google、GitHub、微信)
实现思路:
用户在 SSO 服务器 登录,返回 token
其他系统使用 token
请求 SSO,获取用户信息
通过 OAuth
标准协议授权
window.location.href = `https://sso.example.com/oauth/authorize?client_id=your-client-id&redirect_uri=${encodeURIComponent(window.location.href)}`
token
app.get('/auth/user', async (req, res) => {
const token = req.headers.authorization?.split(' ')[1]
const user = verifyToken(token) // 解析 JWT
res.json(user)
})
✅ 优点:
支持跨域、跨设备
可用于第三方应用
安全性高
❌ 缺点:
需要后端支持 OAuth 2.0
token
需要存 cookie
或 localStorage
适用于:企业级 SSO(如钉钉、企业微信)
实现思路:
用户登录后,后端将 session
存入 Redis
不同系统请求 SSO,校验 session
是否有效
用户登出时,删除 Redis session
const sessionStore = new Redis() // 连接 Redis
app.post('/login', (req, res) => {
const token = generateToken(req.body.user)
sessionStore.set(token, JSON.stringify(req.body.user), 'EX', 3600) // 存入 Redis
res.json({ token })
})
app.get('/check-session', async (req, res) => {
const token = req.headers.authorization?.split(' ')[1]
const session = await sessionStore.get(token)
if (session) {
res.json(JSON.parse(session))
} else {
res.status(401).json({ message: '未登录' })
}
})
✅ 优点:
可以跨域、跨浏览器共享登录
适用于大规模企业级系统
支持 SSO 统一管理
❌ 缺点:
需要后端支持 Redis
实现较复杂
方案 | 适用范围 | 共享方式 | 安全性 | 适合场景 |
---|---|---|---|---|
localStorage |
同浏览器 | localStorage |
低 | 前端应用 |
BroadcastChannel |
同浏览器 | postMessage |
低 | 单页面应用 |
Cookie + SameSite |
跨子域 | cookie |
中 | 内部 SaaS 系统 |
OAuth 2.0 + JWT |
跨域、第三方 | token |
高 | 公共平台 |
SSO + Redis |
跨系统、跨浏览器 | session |
高 | 企业 SSO |
小型前端应用(SPA) ➝ localStorage + BroadcastChannel
企业 SaaS(跨子域) ➝ Cookie + SameSite=None
第三方登录(跨域) ➝ OAuth 2.0 + JWT
企业级 SSO(跨浏览器、多系统) ➝ Redis + Session
推荐组合:
✅ SSO + OAuth 2.0 + Redis + JWT,适用于高安全性、多端登录