前端权限 UI 设计:按钮隐藏、路由守卫与后端校验的边界
本文目录
前端权限最容易走向两个极端:页面里散落角色字符串,或误以为隐藏按钮就能保护接口。前端负责展示当前主体可用的体验和清楚的拒绝原因;真正授权必须由后端针对主体、动作和目标对象重新判定。
将身份映射为能力
页面代码使用 canReadBook、canEditDocument、canPublish、canManageUsers 等语义化能力,而不是在每个组件比较角色字符串。角色映射集中管理;同一用户可能因资源归属、审核状态、订阅或租户范围而有不同对象权限,所以能力检查可以接受资源上下文。
菜单和路由根据服务端确认的能力裁剪。访客预览后台时,可以显示只读结构与说明;禁用动作应说明为什么不可用,并提供申请访问或返回入口。是否隐藏危险入口是产品体验决定,不是安全边界。
| 页面状态 | 前端呈现 | 仍需服务端执行 |
|---|---|---|
| 未登录 | 保存当前目标后引导登录 | 检查 session、token 与重定向目标 |
| 只读预览 | 清楚标明查看模式,禁用编辑控件 | 拒绝所有写、删除、上传、发布与回滚 API |
| 可编辑但不可发布 | 允许草稿编辑,隐藏或禁用发布并说明原因 | 对 publish 动作单独授权 |
| 对象不可访问 | 显示无权限/不可用状态,不暴露正文 | 每次读取与下载都做对象级检查 |
| 角色刚被撤销 | 更新 UI 并清理私有缓存 | 使旧 session/token 与长连接尽快失效 |
后端授权契约
访问控制应默认拒绝,并在每个 endpoint 明确 public、authenticated、role 或 object-level 条件。列表先以主体权限约束数据库查询,再分页返回,不能取回所有记录后让 UI 过滤。写入、批量操作、导出、搜索、版本历史、封面/附件和 WebSocket 订阅都要纳入同一权限矩阵。
错误响应不要泄露隐藏文档是否存在、内部路径或正文内容。对缓存设定账号与权限边界;切换用户时清理 query cache、IndexedDB、本地持久化与预取请求。角色或资源权限变更需要审计和缓存失效机制。
前端组件组织
权限 hook/store 只负责读取可信的登录态能力快照,避免将任何本地存储中的角色字段当成授权证明。请求层统一处理 401、403、账号冻结、token 过期和二次认证状态;不能把所有失败吞成“网络错误”。多标签页需要同步登出和权限更新事件。
组件分离“不可见”“禁用”“只读”语义,表格操作、快捷键、批量选择、拖放、文件上传和键盘命令都要检查能力,不能只隐藏鼠标按钮。读屏文本也要说明权限限制;测试无障碍时确认禁用状态可被理解。
删除、角色调整、导出和发布等高风险动作可要求二次确认或近期重新认证,并在服务端记录审计。乐观更新只适用于可安全回滚的交互;收到 403 时要恢复原 UI、保留用户输入并说明授权已变化,不能显示“保存成功”后再静默撤销。
状态呈现与可访问性
未登录、只读、可编辑、待审核、已下架和权限过期要有不同的视觉状态与可操作入口。禁用按钮旁说明缺少的能力或审核条件;隐藏操作则要确认不会让使用者误以为数据丢失。加载、403、401 和服务暂不可用分别呈现,并提供不破坏输入内容的恢复方式。
键盘操作、快捷键、上下文菜单、拖放和移动端长按也属于动作入口。使用 disabled 属性或等效语义,保持焦点顺序、读屏名称和状态播报;不能只靠灰色样式表达不可用。切换账号后清掉上一主体的选中项、草稿缓存和预览内容。
权限回归矩阵
对 ADMIN、EDITOR、VIEWER、USER、匿名、已冻结和权限过期等主体逐一测试深层路由直达与 API 直连。用他人对象 ID、隐藏草稿、已下架图书、批量混合权限、版本回滚、文件直链和缓存命中做负向用例。界面没有按钮而 API 返回 200,依然是越权缺陷。
Live Notes
留言提交后会先进入审核,审核通过后对其他读者公开。