在 React js 应用程序中使用 Keycloak 注销用户的问题
Posted
技术标签:
【中文标题】在 React js 应用程序中使用 Keycloak 注销用户的问题【英文标题】:Problem in log out user using Keycloack in React js app 【发布时间】:2021-10-10 02:20:48 【问题描述】:我正在 React js 应用程序中使用 Keycloak 实现身份验证。
在这种情况下,我使用React Context 来管理全局状态是KeycloackContext
中的keycloackValue
和authenticated
。
案例:
-
当应用程序第一次运行时,应用程序会检查
keycloackValue
和authenticated
。它们的初始状态是null
和false
。
如果keycloackValue
和authenticated
是null
和false
,应用程序将初始化keycloak 登录页面(通过在KeycloackContext
中调用keycloak.init
)。
如果keycloackValue
和authenticated
分别是not null
和true
(表示用户通过keycloak登录成功),则应用会渲染MyApp.js
中的所有组件。
如果用户点击Header
组件中的log out button
,应用程序会将keycloackValue
和authenticated
设置为null
和false
,同时调用keycloak注销用户。之后调用keycloak登录页面。
问题:
我使用 keycloak 成功登录。然后app成功渲染了MyApp.js
中的所有组件。
问题是当我点击Header.js
中的log out button
时,keycloackValue
和authenticated
被成功设置为null
和false
,keycloak也成功注销。然后应用自行刷新并渲染MyApp.js
中的所有组件(应用没有调用keycloak登录页面)。
代码:
index.js
import React from "react";
import ReactDOM from "react-dom";
import MyApp from './my/App'
import KeycloackContextProvider from "./my/contexts/KeycloackContext"
ReactDOM.render(
<KeycloackContextProvider>
<MyApp/>
</KeycloackContextProvider>,
document.getElementById("root")
);
KeyclockContext.js
import React, createContext, useState, useEffect from 'react'
// KEYCLOACK
import Keycloak from 'keycloak-js'
const KeycloackContext = createContext()
const KeycloackContextProvider = (props) =>
const [ keycloackValue, setKeycloackValue ] = useState(null)
const [ authenticated, setAuthenticated ] = useState(false)
const setKeycloack = () =>
const keycloak = Keycloak(
realm: process.env.REACT_APP_WULING_KEYCLOAK_REALM,
url: process.env.REACT_APP_WULING_KEYCLOAK_URL,
clientId: process.env.REACT_APP_WULING_KEYCLOAK_CLIENTID,
)
keycloak.init(
onLoad: 'login-required',
checkLoginIframe: false,
).then(authenticated =>
setKeycloackValue(keycloak)
setAuthenticated(authenticated)
)
const logout = () =>
setKeycloack(null)
setAuthenticated(false)
keycloackValue.logout()
useEffect(() =>
setKeycloack()
, [])
return (
<KeycloackContext.Provider
value=
keycloackValue,
authenticated,
logout
>
props['children']
</KeycloackContext.Provider>
)
export KeycloackContextProvider, KeycloackContext
MyApp.js
import React, useContext from 'react'
import BrowserRouter as Router, Switch, Route, Redirect from 'react-router-dom'
import Header from './components/Header/Header'
import Tab from './components/Tab/Tab'
// CONTEXTS
import KeycloackContext from './contexts/KeycloackContext'
import Device from './pages/Device/Device'
import Stock from './pages/Stock/Stock'
const MyApp = () =>
const keycloackValue, authenticated = useContext(KeycloackContext)
return (
(keycloackValue && authenticated) &&
<div className='app-root'>
<Router>
<Header/>
<Tab/>
<Redirect from='/' to='/device'/>
<Switch>
<Route exact path='/device'>
<Device/>
</Route>
<Route exact path='/stock'>
<Stock/>
</Route>
</Switch>
</Router>
</div>
)
export default MyApp
Header.js
import React, useContext from 'react'
// CONTEXTS
import KeycloackContext from '../../contexts/KeycloackContext'
const Header = () =>
const logout = useContext(KeycloackContext)
return (
<div className='logout-popup-root'>
<p className='logout-popup-username'>Username</p>
<p className='logout-popup-email'>username@gmail.com</p>
<div className='logout-popup-divider'></div>
<div
className='logout-popup-logout-button'
onClick=() => logout()
>
Log Out
</div>
</div>
)
export default Header
相关依赖:
"keycloak-js": "^15.0.0",
"react": "16.12.0",
"react-dom": "16.12.0",
"react-router-dom": "5.1.2",
"react-scripts": "3.2.0",
注意:
-
我昨天尝试在另一个应用程序中使用此代码。该应用程序很好(一切都按我的意愿运行)。我不知道为什么这次代码没有像以前的应用程序那样运行。
如果这个问题不够清楚,请告诉我。我会尽快更新。
更新:
-
在之前的应用程序(昨天的应用程序)中,如果我点击注销按钮,应用程序会刷新一次(从 keycloak)并出现 keycloak 登录页面。
在这个应用程序(今天的应用程序)中,如果我单击注销按钮,应用程序将刷新三次(从keycloak),keycloak 识别用户已通过身份验证(
keycloackValue
和authenticated
是not null
和@ 987654363@),keycloak登录页面没有出现。
【问题讨论】:
【参考方案1】:经过几天的尝试和调试,我终于找到了解决方案。
只需评论或删除KeycloackContext.js
中的checkLoginIframe: false
。它解决了注销问题。
Keyclock.js
import React, createContext, useState, useEffect from 'react'
// KEYCLOACK
import Keycloak from 'keycloak-js'
const KeycloackContext = createContext()
const KeycloackContextProvider = (props) =>
const [ keycloackValue, setKeycloackValue ] = useState(null)
const [ authenticated, setAuthenticated ] = useState(false)
const setKeycloack = () =>
const keycloak = Keycloak(
realm: process.env.REACT_APP_WULING_KEYCLOAK_REALM,
url: process.env.REACT_APP_WULING_KEYCLOAK_URL,
clientId: process.env.REACT_APP_WULING_KEYCLOAK_CLIENTID,
)
keycloak.init(
onLoad: 'login-required',
// checkLoginIframe: false, // remove checkLoginIframe here
).then(authenticated =>
setKeycloackValue(keycloak)
setAuthenticated(authenticated)
)
const logout = () =>
setKeycloack(null)
setAuthenticated(false)
keycloackValue.logout()
useEffect(() =>
setKeycloack()
, [])
return (
<KeycloackContext.Provider
value=
keycloackValue,
authenticated,
logout
>
props['children']
</KeycloackContext.Provider>
)
export KeycloackContextProvider, KeycloackContext
【讨论】:
以上是关于在 React js 应用程序中使用 Keycloak 注销用户的问题的主要内容,如果未能解决你的问题,请参考以下文章
在 Immutable.js 中使用 React 的不可变助手
在 react.js 中使用 three.js 创建 WebXR 应用程序时,我不断看到“XRWebGLLayer”未定义 no-undef
使用 Node.js 后端在我的 React 应用程序中启用 CORS