如何从example.com域检查同浏览器内sso.example.com的Keycloak SSO会话存在性?
跨域检查Keycloak SSO会话的可行方案
因为KEYCLOAK_SESSION Cookie属于sso.example.com域,example.com的前端代码无法直接读取,所以得换官方推荐的跨域会话检查方式,以下是两种实用方案:
方案一:用Keycloak登录状态iframe(前端直接实现)
Keycloak自带专门处理跨域会话检查的iframe页面,通过postMessage和父页面通信,这是官方主推的方式,步骤如下:
- 嵌入检查iframe
在example.com的页面中加入隐藏的iframe,指向Keycloak的登录状态端点:
<iframe id="kc-session-check" src="https://sso.example.com/realms/你的Realm名称/protocol/openid-connect/login-status-iframe.html" style="display: none;"></iframe>
- 前端监听并触发会话检查
添加JS代码,通过postMessage和iframe交互,获取会话状态:
// 监听iframe发来的会话状态消息 window.addEventListener('message', (event) => { // 一定要验证消息来源,防止恶意请求 if (event.origin !== 'https://sso.example.com') return; const msg = JSON.parse(event.data); if (msg.type === 'login-status') { // 没有SSO会话就重定向到登录页 if (!msg.loggedIn) { const loginUrl = `https://sso.example.com/realms/你的Realm名称/protocol/openid-connect/auth?client_id=你的Example客户端ID&redirect_uri=https://example.com/回调路径&response_type=code`; window.location.href = loginUrl; } } }); // 页面加载后主动向iframe发请求 window.addEventListener('load', () => { const iframe = document.getElementById('kc-session-check'); iframe.contentWindow.postMessage(JSON.stringify({ type: 'login-status-request' }), 'https://sso.example.com'); });
- Keycloak后台配置
进入你的Realm → 客户端 → 选择example.com对应的客户端 → 在「Web Origins」中添加https://example.com(测试阶段可以填*,生产环境必须指定具体域名),确保跨域通信被允许。
方案二:后端代理检查请求(更安全)
如果担心前端postMessage的安全性,或者需要结合后端业务逻辑,可以让example.com的后端去请求Keycloak的会话端点,后端之间没有跨域限制:
- 后端编写检查接口
以Node.js/Express为例,转发用户浏览器的Cookie到Keycloak的会话状态接口:
app.get('/api/check-keycloak-session', async (req, res) => { try { const kcSessionUrl = 'https://sso.example.com/realms/你的Realm名称/protocol/openid-connect/session-status'; const response = await fetch(kcSessionUrl, { headers: { // 转发用户浏览器的Cookie,包含Keycloak的会话Cookie Cookie: req.headers.cookie || '' }, credentials: 'include' }); const sessionData = await response.json(); // 根据返回结果判断是否存在有效会话 const hasValidSession = sessionData.loggedIn === true; res.json({ hasValidSession }); } catch (err) { // 请求失败默认视为无会话 res.json({ hasValidSession: false }); } });
- 前端调用后端接口
fetch('/api/check-keycloak-session') .then(res => res.json()) .then(data => { if (!data.hasValidSession) { const loginUrl = `https://sso.example.com/realms/你的Realm名称/protocol/openid-connect/auth?client_id=你的Example客户端ID&redirect_uri=https://example.com/回调路径&response_type=code`; window.location.href = loginUrl; } });
关键注意事项
- Cookie设置:在Keycloak后台Realm设置 → Cookies → 把SameSite属性设为
None,同时开启Secure(必须用HTTPS,否则跨域Cookie无法传递)。 - HTTPS强制:跨域会话检查在HTTP环境下会有各种限制,生产环境必须全链路用HTTPS。
- Keycloak 18兼容性:以上方案完全适配Keycloak 18(Quarkus版本),配置路径和老版本一致。
内容的提问来源于stack exchange,提问作者alexanoid
相关产品推荐
相关产品推荐

