Skip to content

权限控制

Ant Design Pro 只提供 access.ts —— 一份布尔值映射 —— 而没有任何界面。 想知道某个角色能做什么,只能去读源码。这里权限模型是数据,因此可以被渲染、编辑与测试。

模型

ts
type Permission = `${Resource}:${Action}`;   // 'orders:update'

DEFAULT_GRANTS: Record<Role, Permission[]>
ROUTE_PERMISSIONS: Record<string, Permission>

应用中不会出现*「这个用户是不是管理员」的判断,只会问「这个用户是否可以执行该操作」* —— 因此新增角色时,永远不需要去翻找写死的角色判断。

使用方式

tsx
// 组件级控制 —— 隐藏而非禁用。禁用状态仍然在向用户展示
// 一项他并不具备的能力。
<Can permission="orders:delete">
  <Button danger>删除</Button>
</Can>

// 命令式
const can = useCan();
if (can('orders:update')) { /* … */ }

路由由 <RequirePermission> 守卫,它读取 ROUTE_PERMISSIONS, 并携带被拒绝的路径跳转至 /403,以便异常页能明确说明拦截了什么。

两个需要了解的设计决定

未登记的路由默认开放。 未出现在 ROUTE_PERMISSIONS 中的路由可以直接访问。 对模板而言这是更安全的失败方式:遗漏一条配置会让页面照常显示,从而被发现并反馈; 反之则会静默隐藏一个谁也解释不清的功能。若需要默认拒绝, 只需反转 canAccessRoute 中的一行。

/403 本身不受守卫。 只有当它始终可达时,跳转到 /403 才有意义 —— 被守卫的 403 页面会无限重定向到它自己。

权限矩阵页

/access 以「角色 × 资源 × 操作」的形式渲染权限。勾选后立即生效: 侧边栏隐藏对应入口、命令面板不再提供该页面、路由跳转至 403,无需刷新。

「编辑某个角色」与「以某个角色的身份」是两回事

矩阵上的选择器决定你正在编辑哪个角色。改变你谁则是独立的「以该身份查看」操作, 且当目标角色无法返回本页时会先弹出确认。

这曾经是一个真实的缺陷:把选择器直接绑定到当前登录角色后,点击「编辑者」就会让你 变成编辑者,而编辑者没有 users:view,守卫会立刻把你踢到 /403 —— 而你唯一能撤销它的页面,恰好就是刚刚失去的那个。

接入真实后端

客户端的权限模型用于渲染 —— 隐藏菜单、控制按钮、拦截路由,它不是安全边界。 请在服务端强制执行同一套权限;否则它只是一层用浏览器控制台就能绕过的界面便利。

基于 MIT 协议发布