目标是让/login 作为唯一的公共(public)路由,一旦登录,用户就拥有基于用户角色的路由。 身份验证是使用 Keycloak 完成的,我从 keycloak.idTokenParsed.preferred_username 获取用户:管理员、经理、工程师、运算符(operator)。 如果运算符(operator)尝试进入角色,受限路线将被重定向到/notauthorized 页面。 (这部分没做) 如果未登录,用户将被重定向到/login 页面。 (这部分已完成/有效)
有更好的方法吗?不重复路由并在 Routes.jsx 中添加其他用户有点困惑。 如何实现角色限制重定向到/notauthorized?
App.js(没有所有导入,并且缺少带有mapStateToProps、mapDispatchToProps和导出默认App的底部部分)
import React, { useEffect } from "react";
import { Route, Redirect, Switch } from "react-router-dom"
let routeWithRole = [];
let user = '';
const AppContainer = ({ keycloak }) => {
if(keycloak && keycloak.token) {
user = keycloak.idTokenParsed.preferred_username
if( user === 'admin') {
routeWithRole = admin;
} else if( user === 'engineer') {
routeWithRole = engineer
} else if(user === 'manager') {
routeWithRole = manager
} else {
routeWithRole = operator
}
}
return (
<div>
{(keycloak && keycloak.token) ?
<React.Fragment>
<Switch>
{routeWithRole.map((prop, key) => {
console.log('App.js Prop & Key ', prop, key)
return (
<Route
path={prop.path}
key={key}
exact={true}
component={prop.component}
/>
);
})}
<Redirect from={'/'} to={'/dashboard'} key={'Dashboard'} />
</Switch>
</React.Fragment>
:
<React.Fragment>
<Switch>
{publicRoutes.map((prop, key) => {
return (
<Route
path={prop.path}
key={key}
exact={true}
component={(props) =>
<prop.component
keycloak={keycloak}
key={key} {...props} />
}
/>
);
})}
<Redirect from={'/'} to={'/login'} key={'login'} />
</Switch>
</React.Fragment>
}
</div>
)
}
Routes.jsx(缺少所有导入)
export const publicRoutes = [
{ path: "/login", type: "public", name: "landing page", component: LandingPageContainer },
]
export const admin = [
{ path: "/createUser", name: "Create User", component: CreateUser},
{ path: "/editUser", name: "Edit User", component: EditUser},
{ path: "/createdashboard", name: "Create Dashboard", component: CreateDashboard },
{ path: "/editashboard", name: "Edit Dashboard", component: EditDashboard },
{ path: "/createcalendar", name: "Create Calendar", component: CreateCalendar },
{ path: "/editcalendar", name: "list of factories", component: EditCalendar },
{ path: "/dashboard", name: "Dashboard", component: Dashboard }
]
export const engineer = [
{ path: "/createdashboard", name: "Create Dashboard", component: CreateDashboard },
{ path: "/editashboard", name: "Edit Dashboard", component: EditDashboard },
{ path: "/dashboard", name: "Dashboard", component: Dashboard },
{ path: "/notauthorized", name: "Not Authorized", component: Notauthorized }
]
export const manager = [
{ path: "/createcalendar", name: "Create Calendar", component: CreateCalendar },
{ path: "/editcalendar", name: "Edit Calendar", component: EditCalendar },
{ path: "/dashboard", name: "Dashboard", component: Dashboard },
{ path: "/notauthorized", name: "Not Authorized", component: Notauthorized }
]
export const operator = [
{ path: "/dashboard", name: "Dashboard", component: Dashboard },
{ path: "/notauthorized", name: "Not Authorized", component: Notauthorized }
]
最佳答案
当我们在 react 初始化之前知道“keycloak”(不是“keycloak”的异步加载数据)时,我会考虑该选项。如果你理解这个想法,你将能够改进
主要思想是显示所有路由,但几乎所有路由都将是 protected 路由。请参阅示例:
render (
<Switch>
<Route exact path="/login"> // public route
<LandingPageContainer />
</Route>
<AuthRoute exact path="/dashboard"> // for any authorized user
<Dashboard />
</AuthRoute>
<AdminRoute path="/create-user"> // only for admin route
<CreateUser />
</AdminRoute>
<AdminOrEngineerRoute path="/create-dashboard"> // only for admin or engineer route
<CreateDashboard />
</AdminOrEngineerRoute>
<Redirect to="/dashboard" /> // if not matched any route go to dashboard and if user not authorized dashboard will redirect to login
</Switch>
);
然后您可以创建如下组件列表:
const AVAILABLED_ROLES = ['admin', 'engineer'];
const AdminOrEngineerRoute = ({ children, ...rest }) {
const role = keycloak && keycloak.token ? keycloak.idTokenParsed.preferred_username : '';
return (
<Route
{...rest}
render={({ location }) =>
AVAILABLED_ROLES.includes(role) && ? (
children
) : (
<Redirect
to={{
pathname: "/login",
state: { from: location }
}}
/>
)
}
/>
);
}
因此 AdminOrEngineerRoute 将只允许管理员或工程师传递到此路由,否则您将获得/登录页面
永远是你的“瘀伤”
关于reactjs - React Router v5.1.2 公共(public)和 protected 经过身份验证和基于角色的路由,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61131446/