--- outline: deep --- # 权限 框架内置了两种权限控制方式: - 通过用户角色来判断菜单或者按钮是否可以访问 - 通过接口来判断菜单或者按钮是否可以访问 ## 前端访问控制 **实现原理**: 在前端固定写死路由的权限,指定路由有哪些权限可以查看。只初始化通用的路由,需要权限才能访问的路由没有被加入路由表内。在登陆后或者其他方式获取用户角色后,通过角色去遍历路由表,获取该角色可以访问的路由表,生成路由表,再通过 `router.addRoutes` 添加到路由实例,实现权限的过滤。 **缺点**: 权限相对不自由,如果后台改动角色,前台也需要跟着改动。适合角色较固定的系统 ### 步骤 - 确保当前模式为前端访问控制模式 调整对应应用目录下的`preferences.ts`,确保`accessMode='frontend'`。 ```ts import { defineOverridesPreferences } from '@vben/preferences'; export const overridesPreferences = defineOverridesPreferences({ // overrides app: { // 默认值,可不填 accessMode: 'frontend', }, }); ``` - 配置路由权限 **如果不配置,默认可见** ```ts {3} { meta: { authority: ['super'], }, }, ``` - 确保接口返回的角色和路由表的权限匹配 可查看应用下的 `src/store/auth`,找到下面代码, ```ts // 设置登录用户信息,需要确保 userInfo.roles 是一个数组,且包含路由表中的权限 // 例如:userInfo.roles=['super', 'admin'] authStore.setUserInfo(userInfo); ``` 到这里,就已经配置完成,你需要确保登录后,接口返回的角色和路由表的权限匹配,否则无法访问。 ### 菜单可见,但禁止访问 有时候,我们需要菜单可见,但是禁止访问,可以通过下面的方式实现,设置 `menuVisibleWithForbidden` 为 `true`,此时菜单可见,但是禁止访问,会跳转403页面。 ```ts { meta: { menuVisibleWithForbidden: true, }, }, ``` ## 后端访问控制 **实现原理**: 是通过接口动态生成路由表,且遵循一定的数据结构返回。前端根据需要处理该数据为可识别的结构,再通过 router.addRoutes 添加到路由实例,实现权限的动态生成。 **缺点**: 后端需要提供符合规范的数据结构,前端需要处理数据结构,适合权限较为复杂的系统。 ### 步骤 - 确保当前模式为后端访问控制模式 调整对应应用目录下的`preferences.ts`,确保`accessMode='backend'`。 ```ts import { defineOverridesPreferences } from '@vben/preferences'; export const overridesPreferences = defineOverridesPreferences({ // overrides app: { accessMode: 'backend', }, }); ``` - 确保接口返回的菜单数据结构正确 可查看应用下的 `src/router/access.ts`,找到下面代码, ```ts {5} async function generateAccess(options: GenerateMenuAndRoutesOptions) { return await generateAccessible(preferences.app.accessMode, { fetchMenuListAsync: async () => { // 这个接口为后端返回的菜单数据 return await getAllMenus(); }, }); } ``` - 接口返回菜单数据,可看注释说明 ::: details 接口返回菜单数据示例 ```ts const dashboardMenus = [ { // 这里固定写死 BasicLayout,不可更改 component: 'BasicLayout', meta: { order: -1, title: 'page.dashboard.title', }, name: 'Dashboard', path: '/', redirect: '/analytics', children: [ { name: 'Analytics', path: '/analytics', // 这里为页面的路径,需要去掉 views/ 和 .vue component: '/dashboard/analytics/index', meta: { affixTab: true, title: 'page.dashboard.analytics', }, }, { name: 'Workspace', path: '/workspace', component: '/dashboard/workspace/index', meta: { title: 'page.dashboard.workspace', }, }, ], }, ]; ``` ::: 到这里,就已经配置完成,你需要确保登录后,接口返回的菜单格式正确,否则无法访问。 ## 按钮细粒度控制 在某些情况下,我们需要对按钮进行细粒度的控制,我们可以借助接口或者角色来控制按钮的显示。 ### 权限码 权限码为接口返回的权限码,通过权限码来判断按钮是否显示,逻辑在`src/store/auth`下: ```ts const [fetchUserInfoResult, accessCodes] = await Promise.all([ fetchUserInfo(), getAccessCodes(), ]); userInfo = fetchUserInfoResult; authStore.setUserInfo(userInfo); accessStore.setAccessCodes(accessCodes); ``` 找到 `getAccessCodes` 对应的接口,可根据业务逻辑进行调整。 权限吗返回的数据结构为字符串数组,例如:`['AC_100100', 'AC_100110', 'AC_100120', 'AC_100010']` 有了权限码,就可以使用 `@vben/access` 提供的`AccessControl`组件及API来进行按钮的显示与隐藏。 #### 组件方式 ```vue ``` #### API方式 ```vue ``` #### 指令方式 ```vue ``` ### 角色 角色判断方式不需要接口返回的权限码,直接通过角色来判断按钮是否显示。 #### 组件方式 ```vue ``` #### API方式 ```vue ``` #### 指令方式 ```vue ```