library-picturebook-activity/frontend/PERMISSION_USAGE.md
2025-11-23 14:04:20 +08:00

379 lines
8.0 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.

# 前端权限控制使用指南
## 📋 概述
前端权限控制系统已经完善,支持:
- ✅ 自动获取用户信息(刷新页面时)
- ✅ 角色权限检查
- ✅ 权限码检查
- ✅ 路由守卫自动验证
## 🔧 已修复的问题
### 1. **认证状态判断**
- **之前**: `isAuthenticated = !!token && !!user`(刷新页面时 user 为 null 导致判断失败)
- **现在**: `isAuthenticated = !!token`(只要有 token 就认为已认证)
### 2. **自动获取用户信息**
- **之前**: 刷新页面后用户信息丢失
- **现在**:
- 应用启动时自动获取(`main.ts`
- 路由守卫中自动获取(如果 token 存在但 user 不存在)
### 3. **权限检查**
- **之前**: 只检查 `requiresAuth`,没有角色和权限检查
- **现在**: 支持角色和权限检查
## 🎯 使用方法
### 1. 在路由中配置权限
#### 使用角色控制
```typescript
{
path: "users",
name: "SystemUsers",
component: () => import("@/views/system/users/Index.vue"),
meta: {
title: "用户管理",
requiresAuth: true,
roles: ["super_admin", "admin"], // 需要 super_admin 或 admin 角色
},
}
```
#### 使用权限控制
```typescript
{
path: "users",
name: "SystemUsers",
component: () => import("@/views/system/users/Index.vue"),
meta: {
title: "用户管理",
requiresAuth: true,
permissions: ["user:read"], // 需要 user:read 权限
},
}
```
#### 同时使用角色和权限
```typescript
{
path: "users",
name: "SystemUsers",
component: () => import("@/views/system/users/Index.vue"),
meta: {
title: "用户管理",
requiresAuth: true,
roles: ["admin"], // 需要 admin 角色
permissions: ["user:read"], // 并且需要 user:read 权限
},
}
```
**注意**: 如果同时设置了 `roles``permissions`,需要**同时满足**两者。
### 2. 在组件中使用权限
```vue
<template>
<div>
<!-- 根据角色显示 -->
<a-button v-if="authStore.hasRole('super_admin')" @click="deleteAll">
删除所有
</a-button>
<!-- 根据权限显示 -->
<a-button v-if="authStore.hasPermission('user:create')" @click="createUser">
创建用户
</a-button>
<!-- 检查多个角色 -->
<a-button
v-if="authStore.hasAnyRole(['admin', 'editor'])"
@click="editUser"
>
编辑用户
</a-button>
<!-- 检查多个权限 -->
<a-button
v-if="authStore.hasAnyPermission(['user:update', 'user:delete'])"
@click="manageUser"
>
管理用户
</a-button>
</div>
</template>
<script setup lang="ts">
import { useAuthStore } from "@/stores/auth";
const authStore = useAuthStore();
</script>
```
### 3. Store 方法说明
#### `hasRole(role: string): boolean`
检查用户是否有指定角色
```typescript
if (authStore.hasRole("super_admin")) {
// 用户是超级管理员
}
```
#### `hasPermission(permission: string): boolean`
检查用户是否有指定权限
```typescript
if (authStore.hasPermission("user:create")) {
// 用户可以创建用户
}
```
#### `hasAnyRole(roles: string[]): boolean`
检查用户是否有任一指定角色
```typescript
if (authStore.hasAnyRole(["admin", "editor"])) {
// 用户是 admin 或 editor
}
```
#### `hasAnyPermission(permissions: string[]): boolean`
检查用户是否有任一指定权限
```typescript
if (authStore.hasAnyPermission(["user:create", "user:update"])) {
// 用户可以创建或更新用户
}
```
## 🔄 工作流程
### 1. 应用启动流程
```
应用启动
检查 localStorage 中是否有 token
如果有 token调用 fetchUserInfo() 获取用户信息
用户信息包含 roles 和 permissions
应用挂载完成
```
### 2. 路由导航流程
```
用户访问路由
路由守卫 beforeEach
检查 token 是否存在
如果 token 存在但 user 不存在 → 自动获取用户信息
检查 requiresAuth → 是否需要登录
检查 roles → 是否有指定角色
检查 permissions → 是否有指定权限
允许/拒绝访问
```
### 3. 登录流程
```
用户登录
调用 authApi.login()
返回 token 和 user 信息(包含 roles 和 permissions
保存 token 到 localStorage
保存 user 到 store
跳转到目标页面
```
## 📝 路由配置示例
### 完整的路由配置示例
```typescript
const routes: RouteRecordRaw[] = [
{
path: "/login",
name: "Login",
component: () => import("@/views/auth/Login.vue"),
meta: { requiresAuth: false },
},
{
path: "/",
component: () => import("@/layouts/BasicLayout.vue"),
redirect: "/workbench",
meta: { requiresAuth: true },
children: [
{
path: "workbench",
name: "workbench",
component: () => import("@/views/workbench/Index.vue"),
meta: {
title: "仪表盘",
requiresAuth: true,
},
},
{
path: "system/users",
name: "SystemUsers",
component: () => import("@/views/system/users/Index.vue"),
meta: {
title: "用户管理",
requiresAuth: true,
permissions: ["user:read"], // 需要查看用户权限
},
},
{
path: "system/roles",
name: "SystemRoles",
component: () => import("@/views/system/roles/Index.vue"),
meta: {
title: "角色管理",
requiresAuth: true,
roles: ["super_admin", "admin"], // 需要管理员角色
},
},
],
},
];
```
## 🎨 实际应用场景
### 场景 1: 根据权限显示菜单
```vue
<template>
<a-menu>
<a-menu-item v-if="authStore.hasPermission('user:read')">
<router-link to="/system/users">用户管理</router-link>
</a-menu-item>
<a-menu-item v-if="authStore.hasRole('admin')">
<router-link to="/system/roles">角色管理</router-link>
</a-menu-item>
</a-menu>
</template>
```
### 场景 2: 根据权限显示按钮
```vue
<template>
<a-table>
<template #action="{ record }">
<a-space>
<a-button
v-if="authStore.hasPermission('user:update')"
@click="edit(record)"
>
编辑
</a-button>
<a-button
v-if="authStore.hasPermission('user:delete')"
danger
@click="remove(record)"
>
删除
</a-button>
</a-space>
</template>
</a-table>
</template>
```
### 场景 3: 组合权限检查
```vue
<template>
<!-- 需要同时满足角色和权限 -->
<a-button
v-if="authStore.hasRole('admin') && authStore.hasPermission('user:delete')"
@click="deleteAll"
>
批量删除
</a-button>
</template>
```
## ⚠️ 注意事项
### 1. 路由守卫是异步的
路由守卫使用了 `async/await`,确保在检查权限前用户信息已加载。
### 2. 权限检查顺序
1. 认证检查(`requiresAuth`
2. 角色检查(`roles`
3. 权限检查(`permissions`
### 3. 403 页面
如果没有权限,会跳转到 `/403` 页面。你可以自定义这个页面。
### 4. 权限更新
如果用户权限发生变化,需要:
- 重新登录,或
- 调用 `authStore.fetchUserInfo()` 刷新用户信息
## 🔍 调试技巧
### 1. 查看当前用户信息
```typescript
import { useAuthStore } from "@/stores/auth";
const authStore = useAuthStore();
console.log("用户信息:", authStore.user);
console.log("角色:", authStore.user?.roles);
console.log("权限:", authStore.user?.permissions);
```
### 2. 检查权限
```typescript
console.log("是否有 admin 角色:", authStore.hasRole("admin"));
console.log("是否有 user:create 权限:", authStore.hasPermission("user:create"));
```
## 📚 总结
现在权限控制系统已经完善:
1.**自动获取用户信息** - 刷新页面不会丢失
2.**路由权限检查** - 支持角色和权限控制
3.**组件权限检查** - 可以在组件中使用权限方法
4.**类型安全** - TypeScript 类型定义完善
可以开始使用权限控制功能了!