Пытаюсь защитить интерфейсную страницу react с помощью сервера keycloak, но у меня эта ошибка ‘keycloak.init (…).then не является функцией’

#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, как показано в примере ниже. (с компонентом-оболочкой)

https://medium.com/@cagline/authenticate-and-authorize-react-routes-component-with-keycloak-666e85662636

Комментарии:

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_adapter

2. да, спасибо, что указали на это .. это для более старой версии