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

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

毒舌时刻

权限管理?听起来就像是前端工程师为了显得自己很专业而特意搞的一套复杂流程。你以为随便加个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

华为S5700交换机SSH/Telnet/Web登录完整配置流程(V200R005C00SPC500)

华为S5700交换机SSH/Telnet/Web登录完整配置流程(V200R005C00SPC500)

一、配置Vlan管理IP地址 system-view # 进入系统视图 sysname Switch # 设置主机名称 interface Vlanif 1 # 进入VLAN 1三层接口 ip address 192.168.1.100 255.255.255.0 # 配置Vlan管理IP地址 undo shutdown # 激活接口 quit 说明:管理IP需与客户端网络可达,端口状态为Up(可通过 display interface brief 确认)。 二、生成RSA密钥对(用于SSH) rsa local-key-pair create # 开始生成RSA密钥对 Input the bits in the modulus[default = 512]

前端核心知识:Vue 3 编程的 10 个实用技巧

前端核心知识:Vue 3 编程的 10 个实用技巧

文章目录 * 1. **使用 `ref` 和 `reactive` 管理响应式数据** * 原理解析 * 代码示例 * 注意事项 * 2. **组合式 API(Composition API)** * 原理解析 * 代码示例 * 优势 * 3. **使用 `watch` 和 `watchEffect` 监听数据变化** * 原理解析 * 代码示例 * 注意事项 * 4. **使用 `provide` 和 `inject` 实现跨组件通信** * 原理解析 * 代码示例 * 优势 * 5. **使用 `Teleport` 实现组件挂载到任意位置** * 原理解析 * 代码示例 * 优势 * 6. **使用 `Suspense` 处理异步组件加载** * 原理解析 * 代码示例 * 优势

前端通用 Token 全流程操作指南(常见常用版)

前端通用 Token 全流程操作指南(常见常用版) 本文梳理 所有前端框架通用 的 Token 操作逻辑,剥离具体项目/技术栈细节,聚焦「获取→存储→使用→过期→清除」的核心生命周期,每个步骤均标注「通用场景+通用方案+注意事项」,适合所有前端开发场景,可直接作为开发速查表。 前置说明:Token 的核心定位 Token 是后端签发的临时访问凭证,核心作用是: 1. 证明“当前用户是谁”(身份认证); 2. 证明“当前用户有权限访问”(权限校验)。 一、第一步:登录成功获取 Token 通用场景 用户通过账号密码/验证码/第三方登录等方式,向后端发起登录请求,后端验证通过后,在响应体中返回 Token。

双剑破天门:攻防世界Web题解之独孤九剑心法(十)

双剑破天门:攻防世界Web题解之独孤九剑心法(十)

免责声明:用户因使用公众号内容而产生的任何行为和后果,由用户自行承担责任。本公众号不承担因用户误解、不当使用等导致的法律责任 **本文以攻防世界部分题为例进行演示,后续会对攻防世界大部分的web题目进行演示,如果你感兴趣请关注** 目录 一:Lottery 二:ics-05 三:总结 一:Lottery 打开后发现这个靶场加载异常缓慢,然后他还给了源码,我们先不看源码先熟悉一下这个网站是什么 这应该是一个类似猜数字游戏,选对7个号码即可得到相应奖励 然后注册 随便输入7个数字发现一个也没中,白费2元 然后我们随便点击这个网站的功能发现如果想要flag需要有相对应的余额 我们这会的思路就是利用bp抓包看看能不能修改我们的余额 好像成功了,我们试一试能不能换flag 居然说没有足够的钱,这个方法不行只要将页面上的数字修改只要刷新就会变回原来的余额 居然不能修改余额那就看看在猜数字的页面有没有突破口,发现其访问了api.php我们继续代码审计 看到如下核心代码,首先随机生成七位数字(random_win_nums)然后将其赋值给$win_number。随后关