首页 > 解决方案 > Keycloak 仅保护特定路线 [客户端]

问题描述

我已经用我的 ReactJS 应用程序实现了 keycloak 身份验证。目前我所有的路线都通过以下方式得到保障。

keyCloak.init({
    onLoad: 'login-required',
    checkLoginIframe: false
}).success(authenticated => {
    if (authenticated) {
        ReactDOM.render(Application, document.getElementById('root'));
    }
});

我仅在身份验证成功时才呈现反应应用程序。但是现在我需要一些不需要密钥斗篷身份验证的公共路径,任何用户都可以去检查。有没有适当的方法来实现这一目标?

标签: reactjsreact-routeropenid-connectkeycloak

解决方案


安装@react-keycloak/web 库

前置要求: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实例作为道具传递

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 实例对象。但是正在使用第二个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 && 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 && roles) {
                return roles.some(r => {
                    const realm =  keycloak.hasRealmRole(r);
                    const resource = keycloak.hasResourceRole(r);
                    return realm || resource;
                });
            }
            return false;
        }

        return isAutherized();
    }

在此处输入图像描述

此外,还有另一种限制其他包装组件的方式,如下例所示。(带有包装组件)

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


推荐阅读