次元图库
36.81M · 2026-03-09
前端权限控制的目的是,根据当前用户的身份控制其能访问的页面和可执行的操作。需要注意的是:前端权限控制主要是为了提升用户体验(如隐藏无权限的菜单,按钮),正真的数据安全必须依赖后端实现。
业界主流的权限管理模型是RBAC(基于角色的访问控制),其核心思想是将"权限"授予"角色",将"角色"授予"用户",实现了用户与权限的逻辑分离,极大的简化了权限的分配与管理。
主要包括用户身份认证、权限分配、权限校验和页面展示控制。
// context/AuthProvider
const AuthContext = createContext(undefined);
export const useAuth = () => useContext(AuthContext);
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
// 从本地存储中恢复用户权限信息
useEffect(() => {
const user = localStorage.getItem('user');
if (user) {
setUser(JSON.parse(user));
}
}, []);
const login = async (username, password) => {
const user = await loginApi(username,password);
setUser(user);
// 登录后缓存用户权限信息
localStorage.setItem('user', JSON.stringify(user));
};
const logout = () => {
setUser(null);
// 登出后清除本地缓存
localStorage.removeItem('user');
};
const hasPermission = (permission: string | string[]): boolean => {
if (!user) return false;
if (Array.isArray(permission)) {
return permission.some(p => user.permissions.includes(p));
}
return user.permissions.includes(permission);
};
const value = {
user,
login,
logout,
hasPermission
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};
// components/AuthRoute.js
import { useAuth } from '../context/AuthProvider'; // 自定义 hook,获取用户信息
const AuthRoute = ({ children, meta }) => {
const { user, hasPermission } = useAuth();
// 用户未登录,重定向到登录页面
if (meta.requiresAuth && !user) {
return <Navigate to="/login" replace />;
}
// 用户没有权限,重定向到未授权页面
if (meta.permission && !hasPermission(meta.permission)) {
return <Navigate to="/403" replace />;
}
// 权限通过,渲染子组件
return children;
};
export default AuthRoute;
// router/index.js
import AuthRoute from '../components/AuthRoute';
const Router = () => {
const element = routes.map(({ path, element:Component, meta }) => ({
path,
element: (
<AuthRoute meta={meta}>
<Component />
</AuthRoute>
)
}));
return <RouterProvider router={createBrowserRouter(routers)} />;
};
export default Router;
import { useAuth } from '../context/AuthProvider'; // 自定义 hook,获取用户信息
export const AuthButton = ({
permission,
children,
onClick,
}) => {
const { hasPermission } = useAuth();
const hasAccess = hasPermission(permission);
if (!hasAccess) {
return null;
}
return (
<button
onClick={onClick}
>
{children}
</button>
);
};
import { AuthButton } from '../components/AuthButton';
export const ContentManagement = () => {
return (
<AuthButton
permission="content.edit"
onClick={() => handleEdit(item.id)}
>
编辑
</AuthButton>
);
};
按钮、表单项等细粒度权限控制,难点在于检查点分散,如果每个按钮都要添加额外的权限控制逻辑,维护成本高;另外权限检查函数频繁执行(如在列表中渲染几十个按钮),可能造成性能问题。
常用的做法是封装自定义 Hook(如 usePermission)或高阶组件,并且缓存组件的权限检查结果。
用户权限信息需要全局共享且保持一致性。难点在于:
解决方案通常是利用 Context全局共享,使用webStorage本地缓存,利用广播实现多标签页同步。
前端权限控制本质是提升用户体验,正真的数据安全必须依赖后端实现。但难点在于: