概念:單點登錄(Single Sign-On, SSO)主要是在多個系統、多個瀏覽器或多個標簽頁之間共享登錄狀態,保證用戶只需登錄一次,就能訪問多個關聯應用,而不需要重復登錄。
💡 方案分類
1. 前端級別 SSO(僅適用于同源)
適用于:同一域名下的多個系統或標簽頁
方案 | 適用范圍 | 共享方式 | 缺點 |
---|---|---|---|
localStorage | 同瀏覽器、同源 | localStorage 共享 token | 不支持跨瀏覽器或隱身模式 |
sessionStorage | 僅當前標簽頁 | sessionStorage | 關閉標簽頁即失效 |
cookie | 同域、所有瀏覽器 | 服務器 Set-Cookie | 不能跨域,容量限制 |
BroadcastChannel | 同瀏覽器、同域 | postMessage 事件廣播 | 僅適用于同瀏覽器 |
2. 前后端結合 SSO(適用于跨域)
適用于:多個子系統,支持不同域名共享登錄
方案 | 適用范圍 | 共享方式 | 適合場景 |
---|---|---|---|
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,前端查詢 | 高并發業務 |
🔹 方案 1:前端 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
)
🔹 方案 2:SSO + Cookie 共享(適用于跨子域)
適用于:跨子域(如 admin.example.com
和 user.example.com
)
💡 實現思路:
-
后端設置
cookie
,作用域為*.example.com
-
前端所有子系統 訪問
cookie
共享登錄狀態 -
跨域設置
SameSite=None; Secure
后端(Node.js 示例)
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
限制較多
🔹 方案 3:OAuth 2.0 + JWT(適用于跨域、第三方登錄)
適用于:多端、第三方應用、社交登錄(如 Google、GitHub、微信)
💡 實現思路:
-
用戶在 SSO 服務器 登錄,返回
token
-
其他系統使用
token
請求 SSO,獲取用戶信息 -
通過
OAuth
標準協議授權
前端 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) // 解析 JWTres.json(user)
})
? 優點:
-
支持跨域、跨設備
-
可用于第三方應用
-
安全性高
? 缺點:
-
需要后端支持
OAuth 2.0
-
token
需要存cookie
或localStorage
🔹 方案 4:SSO + Redis + Session(適用于企業系統)
適用于:企業級 SSO(如釘釘、企業微信)
💡 實現思路:
-
用戶登錄后,后端將
session
存入 Redis -
不同系統請求 SSO,校驗
session
是否有效 -
用戶登出時,刪除 Redis
session
后端
const sessionStore = new Redis() // 連接 Redisapp.post('/login', (req, res) => {const token = generateToken(req.body.user)sessionStore.set(token, JSON.stringify(req.body.user), 'EX', 3600) // 存入 Redisres.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,適用于高安全性、多端登錄