当4个不同权限的用户共用一套系统,怎么防止前台志愿者误删审计日志?这是Project Morpheus在设计之初就要解决的核心问题。
外部黑客往往不是最大的威胁。真正的风险来自内部——权限提升(Privilege Escalation)。一个拥有基础权限的用户,可能通过系统漏洞获取更高权限,造成不可逆的数据损坏。
本文将拆解这套基于React和Express的多角色权限架构,看看如何用技术手段把"人"的因素锁死在安全边界内。
一、JWT认证:权限体系的数字身份证
整个架构的底座是JWT(JSON Web Token)认证。用户登录后,后端签发一个包含以下信息的签名令牌:
- 用户身份标识
- 角色信息(desk_volunteer/warden/supervisor/auditor)
- 所属hostelId(针对宿管员的角色隔离)
这个令牌存储在浏览器端,每次API请求通过Authorization头部携带:
Authorization: Bearer
hostelId字段的设计很关键——它让宿管员自动被限制在自己管理的楼栋范围内,无需每次查询数据库验证权限。这个字段成为后续权限感知API和角色专属仪表盘的基础。
二、混合架构:Express与Serverless的取舍
项目需要同时支持两种部署模式:
- 传统服务器部署(完整Express应用)
- Serverless函数(Vercel/Netlify边缘部署)
最终采用混合架构:中央Express server.js处理路由分发、认证中间件和全局错误处理;每个具体路由拆分为独立的serverless函数:
/api/teams/verify.js
/api/hostels/allocate.js
/api/audit/logs.js
这种设计带来的收益很明确:本地开发时运行完整Express服务器,部署到边缘节点时每个函数独立扩展——而代码库只需要维护一份。
三、双层守卫:为什么前端隐藏按钮不够
前端重应用最常见的安全误区:只在UI层做防护。
React里把删除按钮藏起来,并不能阻止攻击者直接用curl或Postman调用你的API。任何懂网络的用户都可以绕过界面,直接命中后端接口。
Morpheus采用双层守卫架构。
第一层:前端路由守卫
React中实现ProtectedRoute包装组件,在渲染前验证用户角色:
const ProtectedRoute = ({ allowedRoles, children }) => { const { user } = useAuth(); if (!allowedRoles.includes(user.role)) { return ; } return children; };
这样前端代码更简洁,也减少了条件渲染带来的bug。
第二层:后端中间件验证
每个API路由都包裹授权中间件。即使攻击者完全绕过前端,服务器仍会验证:
- 令牌签名是否有效
- 用户角色是否具备该操作权限
- 资源访问范围是否匹配(如hostelId)
if (req.user.role !== "Admin") { return res.status(403).json({ error: "Access denied" }); }
这才是真正的纵深防御(defense-in-depth)——两层验证相互独立,任何一层被突破仍有第二层拦截。
热门跟贴