基于授权等级的用户访问控制与路由保护实现问题咨询
Hey there! Let me walk through my current setup for route protection and role-based access control in a React app, and I'm stuck with an issue I can't figure out.
First, here's how I've implemented my ProtectedRoute (checks if user is authenticated via Redux, redirects to login if not):
import PropTypes from "prop-types"; import { useEffect } from "react"; import { useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; import { RootState } from "src/store"; const ProtectedRoute = ({ children }) => { const navigate = useNavigate(); const { isAuthenticated } = useSelector((state: RootState) => state.login); useEffect(() => { if (!isAuthenticated) { navigate("/"); } }, [isAuthenticated]); return children; }; ProtectedRoute.propTypes = { children: PropTypes.node.isRequired, }; export default ProtectedRoute;
Next, the RolesAuthRoute which checks if the user has the required roles to access a route:
import { ReactNode, Fragment } from "react"; import { Navigate } from "react-router-dom"; import { useUserRoles } from "src/utils/ToastMessage"; interface RolesAuthRouteProps { children: ReactNode; roles: Array<string>; } export function RolesAuthRoute({ children, roles }: RolesAuthRouteProps) { const userRoles = useUserRoles(); const canAccess = userRoles.some(userRole => roles.includes(userRole)); if (canAccess) return <>{children}</>; return <Navigate to="/" />; }
Then the UnProtectedRoute for routes that should only be accessible to unauthenticated users (like login):
import { useSelector } from "react-redux"; import { Navigate, Outlet } from "react-router-dom"; import { RootState } from "src/store"; const UnProtectedRoute = () => { const { isAuthenticated } = useSelector((state: RootState) => state.login); return isAuthenticated ? <Navigate to="/dashboard" replace /> : <Outlet />; }; export default UnProtectedRoute;
Here's my route configuration using react-router-dom:
<BrowserRouter> <Routes> <Route element={<UnProtectedRoute />}> <Route element={<Login />} path="/" /> </Route> <Route path="dashboard" element={ <ProtectedRoute> <RolesAuthRoute roles={["admin"]}> <Dashboard /> </RolesAuthRoute> </ProtectedRoute> } /> <Route path="reports" element={ <ProtectedRoute> <RolesAuthRoute roles={["admin"]}> <DashboardDetails /> </RolesAuthRoute> </ProtectedRoute> } /> </Routes> </BrowserRouter>
And the useUserRoles hook I'm using to get the user's roles (hardcoded for now):
// ToastMessage.tsx export type UserRole = "admin" | "root" | "user"; export function useUserRoles() { // some logic or api call to get the roles // for demonstration purposes it's just hard coded const userRoles: UserRole[] = ["admin", "root"]; // return the current user roles return userRoles; }
The Issue
When I try to navigate to /reports, only the links for the dashboard are rendered, and I can't actually access other protected routes properly. I'm not sure what's causing this—any ideas on what I'm missing here?
备注:内容来源于stack exchange,提问作者Shiva Giri

