公开页、登录后页面和管理员页面要在 router meta 和导航守卫里分清楚。接口权限交给后端兜底。
sub2api/frontend-router
后台页面很容易从菜单开始做。
先有一个侧边栏,再把用户管理、分组管理、账号管理、代理管理、兑换码管理这些入口塞进去。普通用户看不到管理员菜单,管理员能看到更多按钮。界面上看起来,权限好像已经做完了。
更合理的顺序是反过来:先写路由守卫,再做菜单。
菜单只是入口。一个页面到底能不能到达,应该由路由表、route meta、导航守卫和后端校验一起决定。
路由表先分三层
一个管理后台最起码要把页面分成三类。
第一类是公开页面,比如登录和注册。它们不需要认证,甚至要阻止已登录用户反复进入。
第二类是普通用户页面,比如 dashboard、API key、usage、兑换和个人资料。它们需要登录,但不需要管理员角色。
第三类才是管理员页面,比如用户、分组、账号、代理和兑换码管理。它们不仅需要登录,还需要管理员角色。
这三类如果只在组件里临时判断,很快就会散掉。更稳的是把它们先写进路由表:
public route -> requiresAuth: falseuser route -> requiresAuth: trueadmin route -> requiresAuth: true + requiresAdmin: true这样菜单、面包屑、标题和权限判断都能从同一份路由元信息里长出来,而不是每个页面各写一套理解。
守卫挡不住绕过,但能减少误入
前端路由守卫不能代替后端鉴权。
这一点要先说清楚。浏览器里的任何判断都可以被绕过,token 校验、角色校验和接口权限必须在后端完成。
前端守卫仍有它该做的事。
它负责先把常见误入挡住:
- 没登录访问受保护页面,跳回登录页。
- 已登录再访问登录页,回到 dashboard。
- 普通用户访问管理员页面,回到普通入口。
- 登录前想去的地址,用 redirect query 记住。
- 页面标题跟着 route meta 更新。
这些动作挡不住恶意请求,主要是让正常用户少遇到空白页、接口 401、半加载页面或突然消失的菜单。
后端照样验权限;前端只把正常访问流程接顺。
菜单应该读路由,不该自造权限
后台菜单最怕另起一套配置。
路由里写了一份管理员页面,菜单里又写一份管理员页面,面包屑再写一份,页面标题再写一份。短期好改,长期一定会漂移。
更好的做法是让菜单尊重 route meta。
比如路由元信息里已经有:
requiresAuthrequiresAdmintitlebreadcrumbsiconhideInMenu
菜单就不需要重新发明权限判断。它只负责把“当前用户能看到的、没有隐藏的路由”展示出来。
这样新增一个管理员页面时,流程很明确:加 route,写 meta,接组件,更新文档。菜单只是自然跟上,而不是另一个需要手工同步的地方。
懒加载是小服务器友好的默认设置
个人服务的后台不该一上来就把所有页面都打进首屏。
dashboard、keys、usage、profile、admin/users、admin/accounts,这些页面并不是每个用户每次都会打开。用动态 import 做懒加载,首屏 bundle 会更轻,普通用户也不用为管理员页面付出首屏成本。
这主要是很现实的资源约束。
服务器只负责静态文件和 API,本来就不该为了一个管理后台增加太多前端负担。Vite 和 Vue Router 已经能把路由组件拆开,就顺手用好。
对个人站和小后台来说,性能优化不一定是复杂缓存。很多时候,先别把用不到的页面塞进首屏,就已经够有效。
redirect query 是小细节,也是状态交代
没有登录时访问 /admin/users,系统不能只说“你没权限”。
更自然的流程是:先跳到登录页,并把原始目标放进 redirect query。登录成功后,如果用户确实有权限,再回到原目标;如果没有权限,再落到普通 dashboard。
这个细节很小,但能让用户登录后不必重新找入口。
没有 redirect,用户登录后还要自己重新找入口。对后台工具来说,这种摩擦很容易被忽视,但每天用就会烦。
404 和刷新也属于路由设计
路由 README 里提到一个常见问题:刷新页面时 404。
这是单页应用的老问题。用户直接访问一个前端路由,服务器如果不知道要回 index.html,就会把它当成真实文件路径处理。
所以路由设计不只在前端。部署层也要配合:
unknown frontend route -> index.htmlapi route -> backendstatic asset -> file否则本地开发一切正常,线上刷新就炸。很多后台看起来是前端问题,实际是部署层没有理解 SPA 路由。
新增页面要有一条固定路径
把新增后台页面的步骤固定下来是个好习惯:
- 在 routes 数组里加路由定义。
- 创建 view 组件。
- 设置
requiresAuth/requiresAdmin。 - 用动态 import 懒加载组件。
- 更新路由文档。
这条流程很朴素,但它能避免后台越来越像临时拼出来的页面集合。
尤其是管理员页面,不能因为“只是加一个入口”就跳过 meta。没有 meta,菜单不知道怎么展示;没有 role 标记,守卫不知道怎么拦;没有文档,后续维护者不知道这个页面属于哪一层。
前端能拦,后端必须再验
最后还是要回到安全问题。
前端守卫可以让普通用户不进入管理员视图,但它不能证明接口安全。用户可以直接请求 API,也可以篡改前端状态。所以后台接口必须每次验证 token,必须在服务端判断 admin role,不能相信前端路由已经拦过。
所以路由说明里那句 client-side only 不能省。
前端守卫负责减少误入和改善体验;后端校验负责授权。菜单、路由、接口三层各管一段,后台才不容易在功能变多后变形。
后台页面不是先把菜单画出来就完了。
先把路由表写清楚,菜单才不会被迫变成权限系统的替身。
继续读