RBAC 角色权限控制

3 阅读3分钟

在 Vue 项目中如何实现 RBAC 角色权限控制 ,可以从 前端架构、权限存储、路由守卫、指令控制、组件封装等方面 进行详细阐述。


1. RBAC 角色权限模型

RBAC(基于角色的访问控制)通常有以下几层:

  • 用户(User) :每个用户都有一个或多个角色。
  • 角色(Role) :角色定义了一组权限。
  • 权限(Permission) :具体的操作权限,比如 "view_dashboard""edit_user"

在 Vue 前端,我们会从后端获取当前用户的角色和权限,然后:

  1. 动态控制路由(哪些页面可以访问)。
  2. 控制 UI 元素(按钮、菜单、表单项的显示)。
  3. 支持多角色(如 admin、editor、user)

2. Vue 前端权限存储

(1)用户角色 & 权限存储

在 Vuex / Pinia 里存储用户角色和权限,方便全局访问。

📌 使用 Pinia

// store/user.js
import { defineStore } from "pinia";

export const useUserStore = defineStore("user", {
  state: () => ({
    roles: [], // 用户角色,例如 ["admin"]
    permissions: [] // 具体权限,例如 ["view_dashboard", "edit_user"]
  }),
  actions: {
    setUserRoles(roles) {
      this.roles = roles;
    },
    setUserPermissions(permissions) {
      this.permissions = permissions;
    }
  }
});

📌 作用

  • 用户登录后,从后端获取 角色 & 权限,存入 Pinia
  • 其它组件可以直接访问 userStore.rolesuserStore.permissions

3. 路由权限控制

(1)前端路由配置

Vue 使用 vue-router,我们可以通过 meta 字段 设置哪些角色可以访问某个页面。

// router/index.js
import { createRouter, createWebHistory } from "vue-router";
import { useUserStore } from "@/store/user";

const routes = [
  {
    path: "/dashboard",
    component: () => import("@/views/Dashboard.vue"),
    meta: { roles: ["admin", "editor"] } // 只有 admin 和 editor 能访问
  },
  {
    path: "/user",
    component: () => import("@/views/User.vue"),
    meta: { roles: ["admin"] } // 只有 admin 能访问
  }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

// 全局路由守卫
router.beforeEach((to, from, next) => {
  const userStore = useUserStore();
  const userRoles = userStore.roles;

  if (to.meta.roles && !userRoles.some(role => to.meta.roles.includes(role))) {
    next("/403"); // 无权限跳转到403页面
  } else {
    next();
  }
});

export default router;

📌 作用

  • meta.roles 限定角色访问权限。
  • beforeEach 守卫拦截 无权限用户 并跳转到 403 页面。

4. 自定义指令控制 UI 权限

我们可以用 v-permission 指令控制 按钮 / 菜单 / UI 组件

(1)定义 v-permission 指令

// directives/permission.js
import { useUserStore } from "@/store/user";

export default {
  mounted(el, binding) {
    const userStore = useUserStore();
    const permissions = userStore.permissions;
    const requiredPermission = binding.value;

    if (!permissions.includes(requiredPermission)) {
      el.parentNode && el.parentNode.removeChild(el); // 无权限则删除元素
    }
  }
};

(2)在 main.js 中注册

import { createApp } from "vue";
import App from "./App.vue";
import permissionDirective from "./directives/permission";

const app = createApp(App);
app.directive("permission", permissionDirective);
app.mount("#app");

(3)在组件中使用

<button v-permission="'delete_user'">删除用户</button>

📌 效果

  • 如果用户 没有 delete_user 权限,按钮不会显示

5. 角色权限动态渲染菜单

菜单项应该根据用户角色动态渲染

<template>
  <ul>
    <li v-if="hasPermission('view_dashboard')">仪表盘</li>
    <li v-if="hasPermission('manage_users')">用户管理</li>
  </ul>
</template>

<script setup>
import { useUserStore } from "@/store/user";
const userStore = useUserStore();

const hasPermission = (perm) => {
  return userStore.permissions.includes(perm);
};
</script>

📌 效果

  • 菜单项 只有用户 拥有相应权限 时才会渲染。

6. 角色权限管理后台

后端管理页面,可以动态配置角色的权限,并存入数据库:

<template>
  <h3>角色管理</h3>
  <ul>
    <li v-for="role in roles" :key="role">
      <span>{{ role }}</span>
      <button @click="setPermissions(role)">设置权限</button>
    </li>
  </ul>
</template>

<script setup>
import { ref } from "vue";

const roles = ref(["admin", "editor", "user"]);

const setPermissions = (role) => {
  console.log("修改权限:", role);
  // 这里可以调用后端 API 修改权限
};
</script>

📌 效果

  • 管理后台可以修改角色权限,前端根据 最新权限 渲染 UI。

7. 结合后端的 API

前端在用户登录后,调用 API 获取用户权限:

// 登录后获取权限
async function fetchUserData() {
  const res = await fetch("/api/user-info"); // 假设后端返回 { roles: ['admin'], permissions: ['view_dashboard', 'edit_user'] }
  const data = await res.json();

  userStore.setUserRoles(data.roles);
  userStore.setUserPermissions(data.permissions);
}

📌 这样即使后端修改了角色权限,前端也能实时更新!


8. 总结

功能实现方式
存储用户权限Pinia (roles & permissions)
路由权限控制router.beforeEach() 拦截
UI 权限控制v-permission 指令
菜单权限控制v-if="hasPermission()" 动态渲染
后端 API 支持登录时获取 roles & permissions

前端基于 RBAC 的权限管理思路

  1. 后端返回角色 & 权限
  2. 存入 Pinia,前端全局可用
  3. 路由守卫控制页面访问
  4. 指令 & v-if 控制 UI
  5. 动态管理权限,前端自动适应

🚀 这样即使后端修改了角色权限,前端也能实时更新 UI & 路由!