使用 keycloak 保护特定的反应页面

Posted

技术标签:

【中文标题】使用 keycloak 保护特定的反应页面【英文标题】:Secure specific react page using keycloak 【发布时间】:2022-01-14 04:57:48 【问题描述】:

我正在将 Keycloak 的身份验证恶魔项目构建到一个反应项目中。 我有一个公共页面和一个私人页面。 私人页面检查用户是否已登录,并根据连接状态显示登录或注销按钮。这部分效果很好。当我单击登录按钮时,我被重定向到 Keycloak 门户。登录后,我被重定向到私人页面,我可以使用专用按钮退出。

但是当我导航到公共页面并返回私人页面时,或者只是刷新私人页面时,连接似乎已断开。然后我点击登录按钮,连接回来了,没有被重定向到 keycloak 门户。

那里有私人页面:

import React from "react";
import Nav from "../modules/Nav";
import RenderAnonymous from "../modules/RenderAnonymous";
import RenderAuthenticated from "../modules/RenderAuthenticated";
import UserService from "../services/UserService";

const Private = () => 
    return (
        <>
            <Nav/>
            <RenderAnonymous>
                <p>Il faut s'authentifier</p>
                <button onClick=UserService.doLogin className="btn login-btn">Se connecter</button>
            </RenderAnonymous>
            <RenderAuthenticated>
                <p>User info</p>
                <button onClick=UserService.doLogout className="btn login-btn">Déconnexion</button>
            </RenderAuthenticated>
            <div className="private">
                <h2>Page privée</h2>
            </div>
        </>
    );
;

export default Private;

RenderAnonymous 和 RenderAuthenticated 是相同的,除了身份验证条件:

import UserService from "../services/UserService";

const RenderAuthenticated = (children) => 
    if (UserService.isAuthenticated()) 
        return (children);
    
    return null;
;


export default RenderAuthenticated;

用户服务:

import keycloak from "keycloak-js";

const KC = new keycloak("/keycloak.json");

const initKeycloak = (authenticatedCllback) => 
    KC.init(
        onLoad: "check-sso"
    ).then((auth)=>
        if (auth) 
            console.info("Already logged in");
         else 
            console.info("Need to log in");
        
        authenticatedCllback();
    ).catch((err)=>
        console.error(err);
    );


const doLogin = () => 
    return KC.login();


const doLogout = () => 
    return KC.logout();


const isAuthenticated = () => 
    return KC.authenticated;


const UserService = 
    initKeycloak,
    doLogin,
    doLogout,
    isAuthenticated,
;

export default UserService;

keycloak的初始化是从index.js启动的:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import UserService from "./services/UserService";

const renderApp = () => ReactDOM.render(<App/>,document.getElementById("root"));

UserService.initKeycloak(renderApp);

我不明白问题出在哪里... 是流量问题吗? https://www.keycloak.org/docs/latest/securing_apps/index.html#_javascript_implicit_flow

【问题讨论】:

【参考方案1】:

在我看来,您应该将 keycloak 对象(和 UserService)集成到反应处理中。目前它似乎不在您的&lt;App/&gt; 之外。

例如,您可以使用React context 来保存keycloak 实例。但是您不需要自己实现它。已经有一个名为react-keycloak 的库实现了这种方法。

【讨论】:

谢谢马蒂亚斯,我会试试这个 我实现了 react-keycloak 但我有同样的问题。每次刷新页面时连接都会过期。我没有看到请求附加任何 cookie 或授权标头。我需要使用 redux 之类的东西吗? 当您说“连接”时,您的意思是令牌吗?如果是,那么令牌当然有一个到期时间 (TTL),您需要使用刷新令牌来获取新令牌。 “刷新页面”是指按 F5 或 CTRL-R?如果是,这就是它的工作原理。每次加载页面时,都会完成 keycloak 往返以接收令牌,但这通常对用户不可见。 当我说连接时,它是关于 keycloak.authenticated 属性的结果。我不明白令牌的存储位置以及反应应用程序如何使用它。 当我说刷新时,是的,它是 F5。但是页面会自行刷新,大约每 5 秒刷新一次。我显示一条消息指示身份验证状态(来自 keycloak.authenticated),并且按钮更改为显示“登录”或“注销”。当页面自行刷新时,状态变为“未通过身份验证”,按钮切换为“登录”

以上是关于使用 keycloak 保护特定的反应页面的主要内容,如果未能解决你的问题,请参考以下文章

空闲超时后,由 Keycloak 客户端应用程序保护重定向到登录页面。应用程序位于应用程序网关后面

keycloak,用户注册。如何添加角色?

Keycloak,如何保护不提供网页的 Spring Boot 后端?

撤销 Keycloak 访问令牌

如何使用 keycloak 对 loopback 4 应用程序进行身份验证

无法在 keycloak 上查看登录页面