Files
rxthinkcmf-wiki/RXThinkCMF_Laravel13_EleVue/zh/frontend/permission.md
T
2026-10-08 17:50:29 +08:00

116 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 9.7 权限控制
:::tip 概述
前端权限控制通过 `v-perm` / `v-perms` 指令实现按钮级权限控制。**前端权限只是体验层**(隐藏按钮),真正的安全防线是后端 `#[Permission]` 注解 + `auth.jwt` 中间件。
:::
## 权限指令
### v-perm(单权限)
```vue
<template>
<!-- 只有拥有 sys:user:add 权限的用户才能看到此按钮 -->
<el-button v-perm="['sys:user:add']" type="primary">新增</el-button>
</template>
```
### v-perms(多权限,满足任一即可)
```vue
<template>
<!-- 拥有 sys:user:add 或 sys:user:update 任一权限即可 -->
<el-button v-perms="['sys:user:add', 'sys:user:update']">操作</el-button>
</template>
```
## 指令实现
```typescript
// ui/src/directives/permission.ts
import { usePermission } from '@/hooks/web/usePermission';
export const perm: ObjectDirective = {
mounted(el: HTMLButtonElement, binding) {
const { hasSomePermission } = usePermission();
if (!hasSomePermission(binding.value)) {
el.parentNode.removeChild(el); // 无权限则移除元素(非隐藏)
}
},
};
```
:::tip 移除而非隐藏
无权限时元素直接从 DOM **移除**(而非 `display:none`)——避免通过开发者工具看到"隐藏"的敏感操作按钮。
:::
## usePermission Hook
:::tip 超级管理员
用户权限列表包含 `*:*:*` 时,表示超级管理员,拥有所有权限。
:::
```typescript
// ui/src/hooks/web/usePermission.ts
export function usePermission() {
const userStore = useUserStore();
/**
* 检查是否拥有指定权限
* 超级管理员(permissions 包含 '*:*:*')拥有所有权限
*/
function hasSomePermission(permission: string | string[]): boolean {
const perms = userStore.permissions;
if (perms.includes('*:*:*')) return true;
if (typeof permission === 'string') {
return perms.includes(permission);
}
return permission.some((p) => perms.includes(p));
}
return { hasSomePermission, hasEveryPermission };
}
```
## 权限数据来源
用户登录后,`GET /api/index/getUser` 接口返回权限列表(`IndexService::getUser` → `JwtService::getUserPermissions`,与后端鉴权同一缓存):
```json
{
"permissions": [
"sys:user:page",
"sys:user:add",
"sys:user:update",
"sys:user:delete",
"sys:role:page"
]
}
```
超级管理员返回 `["*:*:*"]`,拥有所有权限。
## 权限码对应关系
| 端 | 机制 | 示例 |
|----|------|------|
| 后端 | `#[Permission('sys:user:add', '添加用户')]` 注解 + 中间件反射鉴权 | 403 拦截 |
| 前端 | `v-perm="['sys:user:add']"` 指令 | 按钮移除 |
| 菜单 | `laravel_menu.permission` 字段(type=1 权限节点) | 角色树勾选 |
三处权限码必须**完全一致**(`sys:{模块}:{操作}`)。
## 常见问题
| 现象 | 原因 | 处理 |
|------|------|------|
| 按钮不显示但接口可调 | 角色有权限码但 `getUser` 未返回 | 重新登录刷新权限缓存 |
| 按钮显示但接口 403 | 菜单 permission 与注解不一致 | 逐字符比对权限码 |
| 超管按钮仍隐藏 | permissions 未含 `*:*:*` | 检查 `getUser` 返回(uid=1 应为通配) |
| 修改角色权限后前端无变化 | 前端权限缓存在 Store | 重新登录或刷新页面 |
详见 [5.4 权限管理(RBAC)](/zh/core/rbac.html)。