前端权限管理实现:别让用户看到不该看的东西!

前端权限管理实现:别让用户看到不该看的东西!

毒舌时刻

权限管理?听起来就像是前端工程师为了显得自己很专业而特意搞的一套复杂流程。你以为随便加个if语句就能实现权限管理?别做梦了!到时候你会发现,权限逻辑分散在各个组件中,难以维护。

你以为前端权限管理就是最终的安全保障?别天真了!前端权限管理只是为了提高用户体验,真正的安全保障在后端。还有那些所谓的权限管理库,看起来高大上,用起来却各种问题。

为什么你需要这个

  1. 用户体验:良好的权限管理可以为不同角色的用户提供不同的界面,提高用户体验。
  2. 安全性:前端权限管理可以防止用户访问不该访问的功能,提高应用的安全性。
  3. 代码组织:集中的权限管理可以使代码结构更清晰,便于维护。
  4. 可扩展性:良好的权限管理设计可以方便地添加新的角色和权限。
  5. 合规性:某些行业和地区要求应用必须实现严格的权限控制。

反面教材

// 1. 分散的权限逻辑 function AdminPanel() { const user = useUser(); if (user.role !== 'admin') { return <div>Access denied</div>; } return <div>Admin Panel</div>; } function UserProfile() { const user = useUser(); const userId = useParams().id; if (user.role !== 'admin' && user.id !== userId) { return <div>Access denied</div>; } return <div>User Profile</div>; } // 2. 硬编码权限 function Menu() { const user = useUser(); return ( <nav> <ul> <li><a href="/">Home</a></li> {user.role === 'admin' && <li><a href="/admin">Admin</a></li>} {user.role === 'user' && <li><a href="/profile">Profile</a></li>} {user.role === 'guest' && <li><a href="/login">Login</a></li>} </ul> </nav> ); } // 3. 缺少权限检查 function DeleteUser() { const { userId } = useParams(); const handleDelete = async () => { await fetch(`/api/users/${userId}`, { method: 'DELETE' }); }; return <button onClick={handleDelete}>Delete User</button>; } // 4. 权限管理混乱 const roles = { admin: ['create', 'read', 'update', 'delete'], user: ['read', 'update'], guest: ['read'] }; function checkPermission(user, resource, action) { if (!user || !user.role) { return false; } const rolePermissions = roles[user.role]; return rolePermissions.includes(action); } // 5. 缺少权限状态管理 function ProtectedRoute({ children, requiredRole }) { const user = useUser(); if (!user || user.role !== requiredRole) { return <Redirect to="/login" />; } return children; } 

问题

  • 权限逻辑分散在各个组件中,难以维护
  • 硬编码权限,难以扩展
  • 缺少权限检查,存在安全隐患
  • 权限管理混乱,难以理解
  • 缺少权限状态管理,用户体验差

正确的做法

权限管理设计

// 1. 权限配置 const permissions = { roles: { admin: { name: 'Admin', permissions: ['users:create', 'users:read', 'users:update', 'users:delete', 'dashboard:access'] }, user: { name: 'User', permissions: ['users:read', 'users:update', 'profile:access'] }, guest: { name: 'Guest', permissions: ['login:access', 'register:access'] } }, resources: { users: { name: 'Users', actions: ['create', 'read', 'update', 'delete'] }, dashboard: { name: 'Dashboard', actions: ['access'] }, profile: { name: 'Profile', actions: ['access', 'update'] }, login: { name: 'Login', actions: ['access'] }, register: { name: 'Register', actions: ['access'] } } }; // 2. 权限检查函数 function checkPermission(user, resource, action) { if (!user || !user.role) { return false; } const rolePermissions = permissions.roles[user.role]?.permissions || []; const permissionKey = `${resource}:${action}`; return rolePermissions.includes(permissionKey); } // 3. 角色检查函数 function checkRole(user, requiredRole) { if (!user || !user.role) { return false; } return user.role === requiredRole; } // 4. 权限管理钩子 import { useContext } from 'react'; import { AuthContext } from './AuthContext'; export function usePermission() { const { user } = useContext(AuthContext); return { hasPermission: (resource, action) => checkPermission(user, resource, action), hasRole: (role) => checkRole(user, role), user }; } 

路由权限管理

// 1. 受保护的路由组件 import React from 'react'; import { Navigate, useLocation } from 'react-router-dom'; import { usePermission } from './usePermission'; export function ProtectedRoute({ children, requiredPermissions = [], requiredRole = null }) { const { hasPermission, hasRole, user } = usePermission(); const location = useLocation(); // 检查角色 if (requiredRole && !hasRole(requiredRole)) { return <Navigate to="/unauthorized" state={{ from: location }} replace />; } // 检查权限 if (requiredPermissions.length > 0) { const hasAllPermissions = requiredPermissions.every(({ resource, action }) => hasPermission(resource, action) ); if (!hasAllPermissions) { return <Navigate to="/unauthorized" state={{ from: location }} replace />; } } return children; } // 2. 路由配置 import { createBrowserRouter } from 'react-router-dom'; import ProtectedRoute from './ProtectedRoute'; import Home from './pages/Home'; import Admin from './pages/Admin'; import Profile from './pages/Profile'; import Login from './pages/Login'; import Unauthorized from './pages/Unauthorized'; const router = createBrowserRouter([ { path: '/', element: <Home /> }, { path: '/admin', element: ( <ProtectedRoute requiredRole="admin"> <Admin /> </ProtectedRoute> ) }, { path: '/profile', element: ( <ProtectedRoute requiredPermissions={[{ resource: 'profile', action: 'access' }]}> <Profile /> </ProtectedRoute> ) }, { path: '/login', element: <Login /> }, { path: '/unauthorized', element: <Unauthorized /> } ]); 

UI权限管理

// 1. 权限控制组件 import React from 'react'; import { usePermission } from './usePermission'; export function PermissionGuard({ children, resource, action, fallback = null }) { const { hasPermission } = usePermission(); if (!hasPermission(resource, action)) { return fallback; } return children; } // 2. 角色控制组件 import React from 'react'; import { usePermission } from './usePermission'; export function RoleGuard({ children, role, fallback = null }) { const { hasRole } = usePermission(); if (!hasRole(role)) { return fallback; } return children; } // 3. 条件渲染 import React from 'react'; import { PermissionGuard } from './PermissionGuard'; import { RoleGuard } from './RoleGuard'; function UserActions({ userId }) { return ( <div> <PermissionGuard resource="users" action="update"> <button>Edit User</button> </PermissionGuard> <PermissionGuard resource="users" action="delete"> <button>Delete User</button> </PermissionGuard> </div> ); } function AdminMenu() { return ( <RoleGuard role="admin"> <nav> <ul> <li><a href="/admin/users">Users</a></li> <li><a href="/admin/dashboard">Dashboard</a></li> <li><a href="/admin/settings">Settings</a></li> </ul> </nav> </RoleGuard> ); } 

权限状态管理

// 1. AuthContext import React, { createContext, useState, useEffect } from 'react'; export const AuthContext = createContext(); export function AuthProvider({ children }) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { // 从 localStorage 或 API 获取用户信息 const fetchUser = async () => { try { const userData = localStorage.getItem('user'); if (userData) { setUser(JSON.parse(userData)); } } catch (error) { console.error('Error fetching user:', error); } finally { setLoading(false); } }; fetchUser(); }, []); const login = async (credentials) => { // 登录逻辑 const response = await fetch('/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(credentials) }); const userData = await response.json(); setUser(userData); localStorage.setItem('user', JSON.stringify(userData)); return userData; }; const logout = () => { setUser(null); localStorage.removeItem('user'); }; return ( <AuthContext.Provider value={{ user, loading, login, logout }}> {children} </AuthContext.Provider> ); } // 2. 权限管理钩子 import { useContext } from 'react'; import { AuthContext } from './AuthContext'; import { checkPermission, checkRole } from './permissions'; export function usePermission() { const { user } = useContext(AuthContext); return { hasPermission: (resource, action) => checkPermission(user, resource, action), hasRole: (role) => checkRole(user, role), user }; } // 3. 权限状态更新 function updateUserPermissions(userId, permissions) { // 更新用户权限 return fetch(`/api/users/${userId}/permissions`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ permissions }) }) .then(response => response.json()) .then(data => { // 更新本地存储的用户信息 const user = JSON.parse(localStorage.getItem('user')); user.permissions = data.permissions; localStorage.setItem('user', JSON.stringify(user)); return data; }); } 

最佳实践

// 1. 权限配置中心化 // permissions.js export const permissions = { roles: { admin: { name: 'Admin', permissions: ['users:create', 'users:read', 'users:update', 'users:delete', 'dashboard:access'] }, user: { name: 'User', permissions: ['users:read', 'users:update', 'profile:access'] }, guest: { name: 'Guest', permissions: ['login:access', 'register:access'] } } }; export function checkPermission(user, resource, action) { if (!user || !user.role) { return false; } const rolePermissions = permissions.roles[user.role]?.permissions || []; const permissionKey = `${resource}:${action}`; return rolePermissions.includes(permissionKey); } // 2. 权限管理组件化 // components/PermissionGuard.jsx import React from 'react'; import { usePermission } from '../hooks/usePermission'; export function PermissionGuard({ children, resource, action, fallback = null }) { const { hasPermission } = usePermission(); if (!hasPermission(resource, action)) { return fallback; } return children; } // 3. 路由权限统一管理 // routes.js import { createBrowserRouter } from 'react-router-dom'; import ProtectedRoute from './components/ProtectedRoute'; import Home from './pages/Home'; import Admin from './pages/Admin'; import Profile from './pages/Profile'; const router = createBrowserRouter([ { path: '/', element: <Home /> }, { path: '/admin', element: ( <ProtectedRoute requiredRole="admin"> <Admin /> </ProtectedRoute> ) }, { path: '/profile', element: ( <ProtectedRoute requiredPermissions={[{ resource: 'profile', action: 'access' }]}> <Profile /> </ProtectedRoute> ) } ]); // 4. 权限检查工具函数 // utils/permission.js export function canAccessRoute(user, route) { if (!route.requiredRole && !route.requiredPermissions) { return true; } if (route.requiredRole) { return user?.role === route.requiredRole; } if (route.requiredPermissions) { return route.requiredPermissions.every(({ resource, action }) => checkPermission(user, resource, action) ); } return false; } // 5. 权限状态管理 // hooks/usePermission.js import { useContext } from 'react'; import { AuthContext } from '../contexts/AuthContext'; import { checkPermission, checkRole } from '../utils/permissions'; export function usePermission() { const { user } = useContext(AuthContext); return { hasPermission: (resource, action) => checkPermission(user, resource, action), hasRole: (role) => checkRole(user, role), user }; } 

毒舌点评

权限管理确实很重要,但我见过太多开发者滥用这个特性,导致应用变得过于复杂。

想象一下,当你为了实现权限管理,创建了大量的组件和钩子,结果导致代码量增加了几倍,这真的值得吗?

还有那些过度使用权限管理的开发者,为了控制每个按钮的权限,而忽略了用户体验,结果导致界面变得支离破碎。

所以,在实现权限管理时,一定要把握好度。不要为了权限管理而权限管理,要根据实际需求来决定权限管理的范围。

当然,对于需要严格权限控制的应用来说,完善的权限管理是必要的。但对于简单的应用,过度的权限管理反而会增加开发成本和维护难度。

最后,记住一句话:权限管理的目的是为了保护用户数据和提高用户体验,而不是为了炫技。如果你的权限管理实现导致用户体验变得更差,那你就失败了。

Read more

零基础入门MC.JS WEBMC1.8:10分钟创建你的第一个方块世界

快速体验 1. 打开 InsCode(快马)平台 https://www.inscode.net 2. 输入框内输入如下内容: 生成一个极简的MC.JS WEBMC1.8入门教程项目。包含一个基础的3D场景,地面由绿色方块组成,玩家可以使用WASD移动,鼠标点击放置红色方块。代码要极度简化,每个关键部分都有详细注释说明。提供一个分步教程文档,解释如何修改代码来改变方块颜色、大小和移动速度等基本参数。界面要友好,有明确的操作指引。 1. 点击'项目生成'按钮,等待项目生成完整后预览效果 最近在学习3D游戏开发,发现用MC.JS WEBMC1.8创建简单的方块世界特别适合新手入门。今天就把我的学习过程记录下来,分享给同样想尝试的小伙伴们。 1. 环境准备 不需要安装任何软件,直接打开浏览器就能开始。MC.JS WEBMC1.8是基于Web的简化版Minecraft开发框架,特别适合快速搭建3D场景原型。

手把手教你完成libwebkit2gtk-4.1-0安装配置(Ubuntu 22.04)

从零搞定 libwebkit2gtk-4.1-0 安装:Ubuntu 22.04 下的实战避坑指南 你有没有遇到过这样的场景?写好了一个基于 GTK 4 的本地 Web 应用,信心满满地在 Ubuntu 22.04 上运行,结果终端弹出一行红色错误: error while loading shared libraries: libwebkit2gtk-4.1.so.0: cannot open shared object file 别急——这不是你的代码出了问题,而是系统里少了关键运行时库: libwebkit2gtk-4.1-0 。 这个库是现代 Linux 桌面开发中“嵌入网页”的核心技术组件。它让你能在原生应用里无缝展示 HTML 内容,比如 Markdown

彻底掀翻前端桌子!2026年HTML最被严重低估的神仙功能,直接干废一票JS组件库!

就在上周一,我还在为了一个破下拉菜单,死磕着整整 150 行 JavaScript 代码。这破玩意儿不仅要管展开、收起,还得处理焦点管理和无障碍访问(Accessibility)。更别提那无穷无尽、让人崩溃的 z-index 层级大战了;移动端上按 ESC 键退出的逻辑直接罢工;至于那个“点击空白处自动关闭”的屎山代码,更是让我连吐槽的力气都没有了。 就在我快要砸键盘的时候,我猛然醒悟:Popover API 已经在 2025 年 4 月达成了 Baseline Widely Available(基线广泛可用) 状态!这意味着,它现在已经在 Chrome、Firefox、Safari 和 Edge 里实现了完美的跨浏览器支持。于是,我直接把那个恶心的组件彻底推翻,只用了区区 8 行纯 HTML

Flutter 三方库 shelf_web_socket 的鸿蒙化适配指南 - 实现具备高性能全双工长连接与协议协商能力的端侧服务端架构、支持分布式实时信令与多端协同实战

Flutter 三方库 shelf_web_socket 的鸿蒙化适配指南 - 实现具备高性能全双工长连接与协议协商能力的端侧服务端架构、支持分布式实时信令与多端协同实战

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 shelf_web_socket 的鸿蒙化适配指南 - 实现具备高性能全双工长连接与协议协商能力的端侧服务端架构、支持分布式实时信令与多端协同实战 前言 在进行 Flutter for OpenHarmony 开发时,当我们的鸿蒙应用需要充当“控制中心”角色(如控制智能家居、开启本地调试服务或实现 P2P 实时对抗脚本时),如何在端侧直接拉起一个支持 WebSocket 协议的高性能微服务端?shelf_web_socket 是针对 shelf 后端框架封装的一款官方级 WebSocket 处理器。本文将探讨如何在鸿蒙端构建极致、透明的长连接交互引擎。 一、原直观解析 / 概念介绍 1.1 基础原理 该库本质上是一个 shelf 处理函数(Handler)