场景题: “现有一个大型后台管理系统,包含了超级管理员、运营、财务三个角色。不同角色登录后:
要答好这道题,必须将权限分层为路由级、视图级、接口级来进行阐述。
千万不要在前端把所有的配置路由全写死,然后依靠在组件顶层加 if (role !== 'admin') return <Forbidden />; 来拦截。这是极其不安全的,且会导致首屏打包的 Bundle 无比臃肿。
主流最佳实践:静态路由 + 动态拉取注册
/login、/404、/403。meta: { roles: ['admin', 'editor'] })。.filter()。router.addRoute() 或 React-Router 的动态数组替换机制,将过滤后的安全路由真正在系统生效。Menu 菜单组件渲染。不在树上的页面,不渲染,且用户硬在地址栏敲 URL 会因未注册路由直接被带到 404/403 页面,实现物理隔绝。路由权限只管页面,如果两个角色都能进同一个页面,但“删除”按钮只能超管点击呢?
Vue 生态:自定义指令 v-auth
底层在 v-auth 的 mounted 阶段,去获取全局 Vuex 的权限点数组。如果没命中,直接通过 el.parentNode.removeChild(el) 从真实 DOM 层面把这个按钮阉割掉(不能用 display: none,容易被控制台破解)。
React 生态:高阶包装组件 Auth
底层检测 Context 里的角色信息,不匹配直接返回 null 不进行渲染。
不论前端如何做 addRoute 或者是防君子不防小人的 v-auth,防篡改的最后一道城墙永远在后端。
如果恶意用户通过抓包直接向发起了针对无权限 POST /api/delete 的 HTTP Request:
服务端必须校验 Token 所属角色,直接打回 401 Unauthorized 或 403 Forbidden。前端响应拦截器(Interceptor)中统一捕获 401/403 错误,并强退登出或无情弹窗报错。
Q:如果系统极大,按角色分配权限不够灵活(比如你们既有运营,又有内容审核员,权限交叉严重),怎么办?
A(满分反杀设计架构):
这就说明基于简单的 RBAC(Role-Based Access Control,基于角色的访问控制) 瓶颈出现了。
这时前端的路由配置表中不再应该写死 roles: ['admin'],而是采用更细粒度的资源权限码 (Action Code)。
前端和后端对齐一套权限码,如 PAGE_USER_LIST, BTN_USER_EDIT。
后端直接发给前端一个他所拥有的无边界的 Code 数组:['PAGE_USER_LIST', 'BTN_USER_EDIT', ...]。
前端此时抛开具体的“职位头衔词汇”,只纯粹检测这个权限库中有没有对应的 Code 码即可。把给员工组合分配职权的操作,在后台界面交还给产品的超管自由装配即可。