核心概念
不同域名下的多个子系统共享登录状态
关键原理
### 🔄postMessage + LocalStorage
这种方式的实现原理是登录主系统后,将token通过postMessage发送给子系统,子系统进行message的监听
js
// 主系统登录成功逻辑
const token = "xxxx";
const domains = ["https://sub1.com", "https://sub2.com"];
domains.forEach(domain => {
const iframe = document.createElement("iframe");
iframe.style.display = "none";
iframe.src = `${domain}/sso-sync.html`;
document.body.appendChild(iframe);
iframe.onload = () => iframe.contentWindow.postMessage(token, domain);
});
//子系统sso-sync.html页面
<!-- sub1.com/sso-sync.html -->
<script>
window.addEventListener("message", e => {
if (e.origin === "https://main.com") localStorage.setItem("token", e.data);
});
</script>
该种方式,有一个我一直没理解的就是,需要在主系统的iframe中打开子系统的一个专门的页面用来接收主系统的postMessage,总感觉不是很顺
🔒 反向代理统一入口方案
通过nginx来配置代理,是一个很巧妙的方式,打开逻辑就是将不同域名执行同一个域名的不同的子路径,在浏览器端仍然是一个路径下,实现登录状态的共享
nginx
server {
listen 80;
server_name gateway.com; # 统一入口域名
location /app1 { proxy_pass http://app1.com; }
location /app2 { proxy_pass http://app2.com; }
}
- 所有系统访问入口为
gateway.com/app1、gateway.com/app2,浏览器视为同源。 - 系统间跳转使用相对路径(如
window.location.href = '/app2/home'),避免跨域检测
🧩 CORS + 集中式认证中心方案
适用于独立域名系统且需精细控制跨域权限的场景。具体的实现就是将登录的逻辑交给一个独立的域名下-认证中心,所有的子系统在未登录的情况下,重定向到认证中心进行登录,并在登录后跳回原子系统,并携带token 在后续的子系统登录时采用同样逻辑,跳转到认证中心,因为认证中心已经登录过,所以可以直接回传回第二个子系统,实现一次登录,不同系统的状态共享
- 认证中心设计 :
- 独立部署于
auth-center.com,提供登录页和令牌签发接口。 - 响应头配置:
- 独立部署于
http
Access-Control-Allow-Origin: https://app1.com
Access-Control-Allow-Credentials: true
- 子系统登录跳转 :
- 未登录用户访问
app1.com时,重定向至:
- 未登录用户访问
js
window.location.href = 'https://auth-center.com/login?redirect_uri=' + encodeURIComponent('https://app1.com/callback');
- 令牌传递与验证 :
- 认证中心回调
app1.com/callback?token=xxxx,前端存储令牌至内存或SessionStorage。 - 切换至
app2.com时,重复上述流程,认证中心通过Cookie自动识别已登录用户,直接签发令牌
- 认证中心回调
图表
🔄postMessage + LocalStorage
graph TD
A[用户登录主系统] --> B[主系统生成Token]
B --> C[创建隐藏iframe加载子系统页面]
C --> D[iframe加载完成后发送postMessage]
D --> E[子系统监听message事件]
E --> F[接收Token存入LocalStorage]
F --> G[子系统建立本地会话]
CORS + 集中式认证中心方案
graph LR
A[用户访问子系统A] --> B{本地有Token?}
B -->|无| C[重定向至认证中心]
B -->|有| D[验证Token有效性]
C --> E[用户在认证中心登录]
E --> F[认证中心生成Token]
F --> G[重定向回子系统A并附带Token]
G --> H[子系统A验证Token]
H --> I[建立本地会话]
I --> J[用户访问子系统B]
J --> K{本地有Token?}
K -->|无| C
K -->|有| D