#reactjs #keycloak
#reactjs #keycloak
Вопрос:
Я пытаюсь защитить компонент react с помощью keycloak и до сих пор я все делал так, как он сказал:
- Я установил пакеты KEycloak через NPM
- Я поместил keycloak.json в общую папку
- Я изменил свой компонент, чтобы он монтировался при маршрутизации страницы
но в конце я получаю эту ошибку:
keycloak.init(…).then не является функцией
Я попытался заменить вход, требуемый check-sso
вот мой код, введенный в мой компонент:
import Keycloak from 'keycloak-js';
componentDidMount() {
const keycloak = Keycloak('./public/keycloak.json');
keycloak.init({onLoad: 'login-required'}).then(authenticated => {
this.setState({ keycloak: keycloak, authenticated: authenticated })
})
}
render(){
if (this.state.keycloak) {
if (this.state.authenticated)
return (<div className="container text-dark">);
else return (<div>Unable to authenticate!</div>)
}
return (<div>Initializing Keycloak...</div>);
}
Комментарии:
1. Пожалуйста, укажите вашу ошибку в текстовом формате непосредственно в вопросе вместо ссылки на внешнее изображение.
Ответ №1:
Вместо :
const keycloak = Keycloak('./public/keycloak.json');
Попробуйте это:
const keycloak = Keycloak('/keycloak.json');
и установите для promiseType значение native в параметрах инициализации, подобных этому (в вашем случае) :
keycloak.init({onLoad: 'login-required', promiseType: 'native'}).then(authenticated => {
this.setState({ keycloak: keycloak, authenticated: authenticated })
})
Ответ №2:
Пожалуйста, проверьте, что keycloak.json содержит эти значения:-
{
"realm": "...",
"auth-server-url": "http://...",
"ssl-required": "none",
"resource": "...",
"public-client": true,
"confidential-port": 0
}
Комментарии:
1. это мой keycloak.json { «realm»: «insapi», «auth-server-url»: » localhost: 8080 / auth «, «ssl-required»: «external», «resource»: «simulgarantie», «public-client»: true, «confidential-port»: 0 }
2. @Samar пожалуйста, проверьте с помощью
"ssl-required":"none"
, поскольку URL-адрес auth-server — localhost и ssl-сертификат не добавлен3. Все та же ошибка, инициализация функции неизвестна, я предполагаю, что есть адаптер javascript, который я должен где-то добавить
Ответ №3:
Это может помочь вам, но это реализовано с помощью другой библиотеки, но вы можете ограничить маршруты / компоненты / функции React
Установите @react-keycloak / веб-библиотеку
Предварительно требуется: keycloak-js 9.0.2 или более поздней версии
npm install --save keycloak-js
npm install --save @react-keycloak/web
Создайте keycloak.js
файл в src
папке вашего проекта со следующим содержимым, чтобы настроить экземпляр Keycloak по мере необходимости.
Настройте экземпляр Keycloak
import Keycloak from 'keycloak-js'
const keycloakConfig = {
url: 'http://localhost:8080/auth',
realm: 'Demo',
clientId: 'react-app'
}
const keycloak = new Keycloak(keycloakConfig);
export default keycloak
Затем оберните ваше приложение внутрь KeycloakProvider
и передайте keycloak
экземпляр в качестве prop
import React from 'react';
import { KeycloakProvider } from '@react-keycloak/web'
import keycloak from './keycloak'
import AppRouter from './routes'
const App = () => {
return (
<KeycloakProvider keycloak={keycloak}>
<AppRouter/>
</KeycloakProvider>
)
}
Как вы видите в компоненте AppRouter useKeycloak
используется без первого параметра, потому что нам не нужен этот объект экземпляра keycloak для использования. Но используется 2-й initialized
параметр, потому что PrivateRoute
используется экземпляр keycloak, а объект keycloak должен быть доступен при PrivateRoute
инициализации, это означает, что до тех пор, пока не будут возвращены маршруты, инициализированные keycloak
import { useKeycloak } from '@react-keycloak/web';
import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Menu from '../components/Menu';
import HomePage from '../pages/HomePage';
import { PrivateRoute } from '../utilities/PrivateRoute';
import ProtectedPage from '../pages/ProtectedPage';
export const AppRouter = () => {
const [, initialized] = useKeycloak();
if (!initialized) {
return <h3>Loading ... !!!</h3>;
}
return (<>
<Menu />
<BrowserRouter>
<Switch>
<Route exact path="/" component={HomePage} />
<PrivateRoute roles={['RealmAdmin']} path="/protected" component={ProtectedPage} />
</Switch>
</BrowserRouter>
</>
);
};
Создайте PrivateRoute.js
файл в src/utilities
папке вашего проекта со следующим содержимым.
import { useKeycloak } from '@react-keycloak/web';
import React from 'react';
import { Redirect, Route } from 'react-router-dom';
export function PrivateRoute({ component: Component, roles, ...rest }) {
const [keycloak] = useKeycloak();
const isAutherized = (roles) => {
if (keycloak amp;amp; roles) {
return roles.some(r => {
const realm = keycloak.hasRealmRole(r);
const resource = keycloak.hasResourceRole(r);
return realm || resource;
});
}
return false;
}
return (
<Route
{...rest}
render={props => {
return isAutherized(roles)
? <Component {...props} />
: <Redirect to={{ pathname: '/', }} />
}}
/>
)
}
Давайте посмотрим, как ограничить компоненты / функции с помощью Keycloak.
import { useKeycloak } from '@react-keycloak/web';
export default function AuthorizedFunction(roles) {
const [keycloak, initialized] = useKeycloak();
const isAutherized = () => {
if (keycloak amp;amp; roles) {
return roles.some(r => {
const realm = keycloak.hasRealmRole(r);
const resource = keycloak.hasResourceRole(r);
return realm || resource;
});
}
return false;
}
return isAutherized();
}
Кроме того, есть другой способ ограничить с помощью компонента-оболочки anther, как показано в примере ниже. (с компонентом-оболочкой)
Комментарии:
1. привет, один вопрос по этому поводу, когда я начинаю использовать веб-приложение, щелкая по URL-адресам с частного маршрутизатора, перед каждой страницей я вижу «Загрузка», как это изменить? Спасибо
Ответ №4:
Keycloak теперь использует .success () для разрешенного обещания и .error () для отклоненного обещания при запуске keycloak.init()
const keycloak = Keycloak({
"clientId": "...",
"realm": "...",
"url": "...",
"ssl-required": "...",
"credentials": {
"secret": "...1"
},
"enable-cors": true,
"public-client": true,
"confidential-port": 0
});
keycloak.init({ onLoad: 'login-required' }).success(authenticated => {
this.setState({ keycloak, authenticated: authenticated },loadData)
})
Комментарии:
1. Похоже, вы используете более старую версию Keycloak,
success
которая устарела в пользуthen
. Смотрите руководство для справки: keycloak.org/docs/latest/securing_apps/#_javascript_adapter2. да, спасибо, что указали на это .. это для более старой версии