要實現基於角色的訪問控制(RBAC),並根據不同的場景(如選單項、頁面、元件)顯示不同的反饋資訊(如隱藏、禁用、提示等),可以設計一套完整的解決方案。這個方案需要結合許可權管理、上下文、路由控制和條件渲染等多個方面。以下是一個詳細的實現方案:
1. 設定角色和許可權
首先,定義你的角色和許可權:
const roles = {
ADMIN: 'admin',
EDITOR: 'editor',
VIEWER: 'viewer',
};
const permissions = {
READ: 'read',
WRITE: 'write',
DELETE: 'delete',
};
const rolePermissions = {
[roles.ADMIN]: [permissions.READ, permissions.WRITE, permissions.DELETE],
[roles.EDITOR]: [permissions.READ, permissions.WRITE],
[roles.VIEWER]: [permissions.READ],
};
2. 許可權上下文
建立許可權上下文,用於在整個應用中共享當前使用者的角色和許可權資訊:
import React, { createContext, useContext } from 'react';
const PermissionsContext = createContext();
export const PermissionsProvider = ({ currentUser, children }) => {
return (
<PermissionsContext.Provider value={currentUser}>
{children}
</PermissionsContext.Provider>
);
};
export const usePermissions = () => {
return useContext(PermissionsContext);
};
3. 建立許可權檢查函式
實現一個函式,用於檢查當前使用者是否具有特定許可權:
const hasPermission = (role, requiredPermission) => {
const userPermissions = rolePermissions[role] || [];
return userPermissions.includes(requiredPermission);
};
4. 建立高階元件和組合元件
實現一個高階元件(HOC)和組合元件,用於許可權控制:
高階元件(HOC)
import React from 'react';
import { usePermissions } from './PermissionsContext';
const withAuthorization = (WrappedComponent, requiredPermission) => {
return (props) => {
const currentUser = usePermissions();
const userRole = currentUser.role;
if (hasPermission(userRole, requiredPermission)) {
return <WrappedComponent {...props} />;
} else {
return <div>Access Denied</div>; // 或者返回其他元件如 <Redirect />
}
};
};
export default withAuthorization;
組合元件
import React from 'react';
import { usePermissions } from './PermissionsContext';
const WithAuthorization = ({ requiredPermission, children, fallback }) => {
const currentUser = usePermissions();
const userRole = currentUser.role;
if (hasPermission(userRole, requiredPermission)) {
return children;
} else {
return fallback || <div>Access Denied</div>;
}
};
export default WithAuthorization;
5. 路由控制
使用 ProtectedRoute
元件控制路由訪問:
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import { usePermissions } from './PermissionsContext';
const ProtectedRoute = ({ component: Component, requiredPermission, ...rest }) => {
const currentUser = usePermissions();
const userRole = currentUser.role;
return (
<Route
{...rest}
render={(props) =>
hasPermission(userRole, requiredPermission) ? (
<Component {...props} />
) : (
<Redirect to="/unauthorized" /> // 或者重定向到 404 頁面
)
}
/>
);
};
export default ProtectedRoute;
6. 選單控制
根據許可權動態生成選單:
import React from 'react';
import { usePermissions } from './PermissionsContext';
import { Link } from 'react-router-dom';
const Menu = () => {
const currentUser = usePermissions();
const userRole = currentUser.role;
return (
<nav>
<ul>
{hasPermission(userRole, permissions.READ) && (
<li>
<Link to="/dashboard">Dashboard</Link>
</li>
)}
{hasPermission(userRole, permissions.WRITE) && (
<li>
<Link to="/editor">Editor</Link>
</li>
)}
{hasPermission(userRole, permissions.DELETE) && (
<li>
<Link to="/admin">Admin</Link>
</li>
)}
</ul>
</nav>
);
};
export default Menu;
7. 元件內許可權控制
在元件內使用組合元件進行許可權控制:
import React from 'react';
import WithAuthorization from './WithAuthorization';
const AdminComponent = () => {
return <div>Admin Content</div>;
};
const App = () => {
return (
<PermissionsProvider currentUser={{ role: roles.EDITOR }}>
<div>
<h1>My App</h1>
<Menu />
<WithAuthorization requiredPermission={permissions.DELETE} fallback={<div>Access Denied</div>}>
<AdminComponent />
</WithAuthorization>
</div>
</PermissionsProvider>
);
};
export default App;
8. 顯示不同的反饋資訊
根據不同的場景顯示不同的反饋資訊:
import React from 'react';
import WithAuthorization from './WithAuthorization';
const DisabledButton = () => <button disabled>You don't have permission</button>;
const AdminComponent = () => {
return <div>Admin Content</div>;
};
const App = () => {
return (
<PermissionsProvider currentUser={{ role: roles.VIEWER }}>
<div>
<h1>My App</h1>
<Menu />
<WithAuthorization requiredPermission={permissions.DELETE} fallback={<DisabledButton />}>
<AdminComponent />
</WithAuthorization>
</div>
</PermissionsProvider>
);
};
export default App;
總結
透過上述步驟,可以實現一套完整的基於 RBAC 的許可權控制方案,涵蓋了選單項、頁面訪問、元件顯示等不同場景的許可權控制。組合方式和高階元件(HOC)各有優勢,可以根據實際需求靈活使用。透過許可權上下文、許可權檢查函式、高階元件和組合元件,可以確保許可權控制邏輯的複用性和靈活性,使得許可權管理更加簡潔和高效。