You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React-router-dom v6结合Keycloak OAuth2实现认证后跳转至目标页面

解决React集成Keycloak的两个核心问题

一、页面重载时保留认证数据

当前AuthProvider的状态只存在内存中,页面刷新就会丢失,必须把认证数据持久化到本地存储:

  1. 同步更新本地存储
    从后端拿到access_token和用户信息后,除了更新组件state,还要存到localStorage(如果希望关闭浏览器就失效,改用sessionStorage):

    // AuthProvider中的状态更新方法
    const setAuth = (token, userInfo) => {
      setToken(token);
      setUser(userInfo);
      // 持久化到本地
      localStorage.setItem('authToken', token);
      localStorage.setItem('authUser', JSON.stringify(userInfo));
    };
    
  2. 初始化时恢复状态
    在AuthProvider挂载时,先读取本地存储的已有数据,恢复认证状态:

    useEffect(() => {
      const savedToken = localStorage.getItem('authToken');
      const savedUser = localStorage.getItem('authUser');
      if (savedToken && savedUser) {
        setToken(savedToken);
        setUser(JSON.parse(savedUser));
      }
    }, []);
    
  3. 登出时清除残留数据
    登出操作要同步删除本地存储的认证信息,避免遗留:

    const logout = () => {
      setToken(null);
      setUser(null);
      localStorage.removeItem('authToken');
      localStorage.removeItem('authUser');
      // 跳Keycloak登出页或首页
      window.location.href = `${keycloakUrl}/logout?redirect_uri=${window.location.origin}`;
    };
    

二、认证完成后跳转回原访问页面

需要在跳转到Keycloak前记录用户最初访问的路径,认证完成后再跳转回去:

  1. 路由守卫中记录原路径
    用React Router自定义PrivateRoute组件,检测到未认证时,先保存当前路径再跳Keycloak授权页:

    const PrivateRoute = ({ children }) => {
      const { token } = useAuth();
      const location = useLocation();
    
      if (!token) {
        // 排除/auth页面,避免循环跳转
        if (location.pathname !== '/auth') {
          // 保存完整路径(包含查询参数)
          localStorage.setItem('redirectPath', `${location.pathname}${location.search}`);
        }
        // 替换成你的Keycloak授权地址
        const keycloakAuthUrl = `${keycloakUrl}/auth?client_id=你的客户端ID&redirect_uri=${encodeURIComponent(window.location.origin + '/auth')}`;
        return <Navigate to={keycloakAuthUrl} replace />;
      }
    
      return children;
    };
    
  2. /auth页面完成认证后跳转
    在/auth页面拿到code、换取token并更新AuthProvider后,读取保存的路径跳转:

    const AuthPage = () => {
      const { setAuth } = useAuth();
      const navigate = useNavigate();
    
      useEffect(() => {
        const code = new URLSearchParams(window.location.search).get('code');
        if (code) {
          fetch(`/api/token?code=${code}`)
            .then(res => res.json())
            .then(data => {
              setAuth(data.access_token, data.userInfo);
              // 读取原路径,默认跳首页
              const redirectPath = localStorage.getItem('redirectPath') || '/';
              // 跳转后清除存储的路径
              localStorage.removeItem('redirectPath');
              navigate(redirectPath, { replace: true });
            })
            .catch(() => navigate('/'));
        }
      }, [setAuth, navigate]);
    
      return <div>正在认证...</div>;
    };
    

额外注意事项

  • 统一使用localStorage或sessionStorage,不要混存避免逻辑混乱。
  • Keycloak控制台配置的redirect_uri必须和代码中的一致,否则会授权失败。
  • 对安全性要求高的场景,可以把原路径加密后放到Keycloak授权请求的state参数中,比本地存储更安全,避免被篡改。

内容的提问来源于stack exchange,提问作者Krishna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 09:10:37