项目背景
在企业级管理后台系统中,用户权限管理是必不可少的模块。
典型需求包括:
- 不同角色访问不同页面和功能
- 动态渲染菜单与按钮
- 后端接口权限控制配合前端渲染
- 可扩展的权限体系,便于后期增加新角色或功能
我所在的项目中,涉及 多层级权限(管理员、部门主管、普通员工)以及 功能粒度控制(按钮、操作权限)。
权限体系设计
角色与权限分离
- 角色(Role):用户所属身份,如
Admin、Manager、Staff - 权限(Permission):具体操作,如
canEditUser、canViewReport
后端返回:
{
"roles": ["Manager"],
"permissions": ["viewDashboard", "editProject", "viewReports"]
}
前端权限控制点
- 页面访问路由控制
- 菜单动态渲染
- 按钮/操作隐藏或禁用
- API 请求前判断权限(避免错误调用)
实战实现
React + Context 管理权限
import React, { createContext, useContext } from 'react';
interface AuthContextType {
roles: string[];
permissions: string[];
}
const AuthContext = createContext<AuthContextType>({
roles: [],
permissions: [],
});
export const useAuth = () => useContext(AuthContext);
export const AuthProvider = ({
children,
roles,
permissions,
}: AuthContextType & { children: React.ReactNode }) => (
<AuthContext.Provider value={{ roles, permissions }}>
{children}
</AuthContext.Provider>
);
路由守卫
import { useAuth } from './AuthContext';
import { Navigate } from 'react-router-dom';
function ProtectedRoute({
children,
requiredPermissions,
}: {
children: React.ReactNode;
requiredPermissions: string[];
}) {
const { permissions } = useAuth();
const hasAccess = requiredPermissions.every((p) => permissions.includes(p));
return hasAccess ? <>{children}</> : <Navigate to="/403" replace />;
}
菜单动态渲染
import { useAuth } from './AuthContext';
const menuItems = [
{ title: 'Dashboard', key: 'dashboard', permission: 'viewDashboard' },
{ title: '项目管理', key: 'project', permission: 'editProject' },
{ title: '报表', key: 'reports', permission: 'viewReports' },
];
function Sidebar() {
const { permissions } = useAuth();
return (
<ul>
{menuItems
.filter((item) => permissions.includes(item.permission))
.map((item) => (
<li key={item.key}>{item.title}</li>
))}
</ul>
);
}
按钮/操作级权限
function EditButton() {
const { permissions } = useAuth();
if (!permissions.includes('editProject')) return null;
return <button className="btn-primary">编辑项目</button>;
}
优化技巧
-
缓存权限信息
使用 localStorage 或全局状态缓存,避免每次渲染重复请求
-
组合权限函数
封装 hasPermission(permission) 函数,统一判断
-
类型安全
在 TypeScript 中使用字符串字面量类型或 enum 定义权限,避免拼写错误
type Permission = 'viewDashboard' | 'editProject' | 'viewReports'; function hasPermission( userPermissions: Permission[], permission: Permission, ) { return userPermissions.includes(permission); } -
与后端权限对齐
前端只做 UI 隐藏,实际敏感操作仍需后端校验
总结
前端权限系统是企业级应用的关键模块:
- 灵活设计角色和权限模型
- SPA 内通过 Context + 路由守卫 + 条件渲染实现动态控制
- 使用 TypeScript 可提高安全性
- 缓存与组合权限判断可提升性能和可维护性
实践中,权限系统越早设计,越容易扩展,同时减少后期迭代的冲突和重复开发。