邓卫洁 發表於 2025-11-4 08:38:00

keycloak~关于跨域的iframe对接keycloak的分析

<h1 id="几个cookie下面元素">几个cookie下面元素</h1>
<ul>
<li>AUTH_SESSION_ID 会话级的session_state</li>
<li>AUTH_SESSION_ID_LEGACY 在http中可见的AUTH_SESSION_ID</li>
<li>KEYCLOAK_SESSION 带有效期的session_state</li>
<li>KEYCLOAK_SESSION_LEGACY在http中可见的KEYCLOAK_SESSION</li>
<li>KEYCLOAK_IDENTITY 用户完成认证后,在cookie记录用户和session_state的jwt token</li>
<li>KEYCLOAK_IDENTITY_LEGACY 在http中可见的KEYCLOAK_IDENTITY</li>
</ul>
<h1 id="不同顶级域名对接keycloak后auth_session_id被cookie-partition隔离">不同顶级域名对接keycloak后auth_session_id被cookie Partition隔离</h1>
<p><img src="https://img2024.cnblogs.com/blog/118538/202510/118538-20251031150454362-1694736641.png" alt="图片" loading="lazy"></p>
<h1 id="登录的过程">登录的过程</h1>
<blockquote>
<p>以社区登录为例,对接社区如微信登录后,在keycloak登录页点微信按钮,</p>
</blockquote>
<ol>
<li>登录页面/auth/realms/demo/protocol/openid-connect/auth</li>
<li>验证参数,完成到社区网站的302跳转/auth/realms/{realm}/broker/weixin/login?client_id=democlient&amp;tab_id=rzukcX7mOfQ&amp;session_code=OPsAHAZ3HZISaxklQLmcVYJThVUwLh5Y8TkAi5GQPjY</li>
<li>在社区网站上完成登录,由社区302跳转回keycloak页面</li>
<li>如果社区帐号没有绑定keycloak用户,进入first-broker-login页面,完成用户的绑定/auth/realms/demo/login-actions/first-broker-login?client_id=democlient&amp;tab_id=JCCx2WFmFFA</li>
<li>在first-broker-login填写信息提交后,完成绑定,302到post-broker-login页面 /auth/realms/demo/login-actions/post-broker-login?client_id=democlient&amp;tab_id=dBh9Jl7qib4</li>
<li>post-broker-login流程处理完成后,302到after-post-broker-login页面,/auth/realms/demo/broker/after-post-broker-login?session_code=QM5PnTZihZqnVsyCilwJhxLY5viLoCgckPLHF_NkBuA&amp;client_id=democlient&amp;tab_id=dBh9Jl7qib4</li>
<li>这样就完成了keycloak的登录,然后302跳转到redirect_uri页面,登录结束</li>
</ol>
<h1 id="跨域iframe登录出现问题的点">跨域iframe登录出现问题的点</h1>
<ol>
<li>打开登录页后,生成auth_session_id这个键,并添加了当前域名的顶级域名做为cookie的<code>Partition Key</code></li>
<li>点击社区登录后,kc服务端进入如下方法</li>
</ol>
<ul>
<li>org.keycloak.services.resources.IdentityBrokerService.performLogin()
<ul>
<li>org.keycloak.services.resources.IdentityBrokerService.parseSessionCode()
<ul>
<li>org.keycloak.services.resources.SessionCodeChecks.initialVerify()</li>
</ul>
</li>
</ul>
</li>
</ul>
<ol start="3">
<li>经过sessionCode初始检查之后,在执行到parseSessionCode()方法中代码AuthenticationSessionModel authSession = checks.getAuthenticationSession();时,authSession的结果为空,故出现无法登录异常,如下代码</li>
</ol>
<pre><code>ERROR (default task-1708) unexpectedErrorHandlingRequestMessage: javax.ws.rs.WebApplicationException: HTTP 400 Bad Request
        at org.keycloak.keycloak-services@14.0.0//org.keycloak.services.resources.IdentityBrokerService.parseSessionCode(IdentityBrokerService.java:1225)
        at org.keycloak.keycloak-services@14.0.0//org.keycloak.services.resources.IdentityBrokerService.performLogin(IdentityBrokerService.java:419)
</code></pre>
<h1 id="跨域后的异常">跨域后的异常</h1>
<ol>
<li>
<p>有同域的auth_session_id的情况下(已在cookie partitioned为空的网站登录,与kc认证服务同一顶级域名),在跨域页面登录,请求是http 302跳到新登录页,显示登录超时(或者强制跳到已登录页面),原因是kc服务端获取的auth_session_id与当前页面传递的tab_id和session_code不匹配<br>
<img src="https://img2024.cnblogs.com/blog/118538/202510/118538-20251031143340030-1713104059.png" alt="图片" loading="lazy"></p>
</li>
<li>
<p>在没有其它auth_session_id的情况下,在跨域页面登录,显示错误页,http 400错误,原因是kc服务端在无法获取cookie中带分区的auth_session_id<br>
<img src="https://img2024.cnblogs.com/blog/118538/202510/118538-20251031143647677-1762089255.png" alt="图片" loading="lazy"></p>
</li>
<li>
<p>keycloak使用了会话保持功能,我们使用更稳定的ingress在浏览器添加cookie的方式,当在社区超链登录时,它的a标签里target属性为_parent或者_top,这样链接发送的cookie是cookie partitioned为空的网站route(状态保持自动生成),这时会出现请求的kc节点与提交的kc节点不同的情况,也会出现400的错误</p>
</li>
</ol>
<h1 id="解决iframe跨域问题的关键">解决iframe跨域问题的关键</h1>
<ol>
<li>表单提交登录,可以适应跨顶域的情况</li>
<li>社区a标签超链登录,如果target=_self,也可以适应跨顶域的情况,其它target属性,不适合</li>
<li>建议统一登录不使用iframe进行嵌入</li>
</ol>


</div>
<div id="MySignature" role="contentinfo">
    <p></p>
<div class="navgood">
<p>作者:仓储大叔,张占岭,<br>
荣誉:微软MVP<br>QQ:853066980</p>

<p><strong>支付宝扫一扫,为大叔打赏!</strong>
<br><img src="https://images.cnblogs.com/cnblogs_com/lori/237884/o_IMG_7144.JPG"></p>
</div><br><br>
来源:https://www.cnblogs.com/lori/p/19179827
頁: [1]
查看完整版本: keycloak~关于跨域的iframe对接keycloak的分析