如何将React组件作为Keycloak回调页面并获取授权码code?
如何将React组件作为Keycloak回调页面并获取授权码code?
看起来你在集成Keycloak到React应用时,卡在了回调页面获取授权码的步骤上。别担心,我来帮你梳理下两种处理方式——一种是Keycloak官方推荐的自动处理方式,另一种是手动提取code的方法。
首先先纠正下你TestLogin组件里的小问题:你在keycloak.init()之后又调用了keycloak.login(),其实当你设置onLoad: 'check-sso'时,init()方法会自动检查用户认证状态,如果未认证就会跳转到Keycloak登录页,不需要手动调用login(),这会导致逻辑重复哦。
一、官方推荐:让Keycloak自动处理回调流程
这是最省心的方式,Keycloak JS适配器会自动解析回调URL里的hash参数(包括code),完成授权并获取token等信息,完全不用你手动提取code。你只需要在回调组件里重新初始化Keycloak即可:
修正后的TestLogin.jsx
import { useEffect } from 'react'; import Keycloak from 'keycloak-js'; // 建议把Keycloak实例放在组件外,避免每次渲染重新创建 const keycloak = new Keycloak({ url: "keycloak.servers", // 替换成你的Keycloak实际服务地址 realm: "master", clientId: "myAppId" }); export default function TestLogin(){ useEffect(() => { const initKeycloak = async () => { try { // onLoad: 'check-sso' 会自动检查登录状态,未登录则跳转到Keycloak登录页 const authenticated = await keycloak.init({ onLoad: 'check-sso', redirectUri: "http://localhost:3000/testCallBack" }); if (authenticated) { console.log('用户已认证,token信息:', keycloak.token); } else { console.log('用户未认证'); } } catch (error) { console.error('初始化Keycloak失败:', error); } }; initKeycloak(); }, []); // 空依赖数组,确保只执行一次 return <div>正在检查登录状态...</div>; }
处理回调的TestCallBack.jsx
import { useEffect } from 'react'; import Keycloak from 'keycloak-js'; const keycloak = new Keycloak({ url: "keycloak.servers", realm: "master", clientId: "myAppId" }); export default function TestCallBack(){ useEffect(() => { const handleCallback = async () => { try { // 初始化Keycloak,它会自动解析hash中的code,完成授权流程 const authenticated = await keycloak.init({ redirectUri: "http://localhost:3000/testCallBack" }); if (authenticated) { console.log('回调处理完成!用户已认证,可访问token:', keycloak.token); // 这里可以跳转到主页或其他需要认证的页面 } else { console.log('回调处理失败,用户未认证'); } } catch (error) { console.error('处理回调失败:', error); } }; handleCallback(); }, []); return <div>正在处理登录回调...</div>; }
二、手动提取URL hash中的code(仅特殊场景使用)
如果你因为某些定制需求必须手动获取code,可以通过解析当前URL的hash部分来提取。在React组件中,借助react-router-dom的useLocation hook就能实现:
手动提取code的TestCallBack.jsx
import { useEffect } from 'react'; import { useLocation } from 'react-router-dom'; export default function TestCallBack(){ const location = useLocation(); useEffect(() => { const parseHashParams = () => { // 去掉hash开头的#,再用URLSearchParams解析参数 const hashContent = location.hash.slice(1); const params = new URLSearchParams(hashContent); const code = params.get('code'); const state = params.get('state'); const sessionState = params.get('session_state'); console.log('手动提取到的code:', code); console.log('对应的state:', state); // 注意:手动拿到code后,你还需要自己调用Keycloak的token端点去换取token, // 这部分逻辑官方适配器已经封装好了,所以非必要不推荐手动处理 }; parseHashParams(); }, [location]); return <div>回调页面,已提取授权码</div>; }
备注:内容来源于stack exchange,提问作者The KNVB
相关产品推荐
相关产品推荐

