当前位置:首页 > VUE

vue 实现权限管理

2026-02-18 14:32:04VUE

路由权限控制

使用Vue Router的beforeEach钩子进行路由拦截,结合用户角色动态过滤路由表。初始化时只加载基础路由,登录后根据角色动态添加可访问路由。

// router.js
const createRouter = () => new Router({
  routes: constantRoutes // 基础路由
})

router.beforeEach(async (to, from, next) => {
  const hasToken = getToken()
  if (hasToken) {
    if (to.path === '/login') {
      next({ path: '/' })
    } else {
      const hasRoles = store.getters.roles.length > 0
      if (hasRoles) {
        next()
      } else {
        try {
          const { roles } = await store.dispatch('user/getInfo')
          const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
          router.addRoutes(accessRoutes)
          next({ ...to, replace: true })
        } catch (error) {
          await store.dispatch('user/resetToken')
          next(`/login?redirect=${to.path}`)
        }
      }
    }
  } else {
    if (whiteList.includes(to.path)) {
      next()
    } else {
      next(`/login?redirect=${to.path}`)
    }
  }
})

动态菜单生成

基于权限路由自动生成侧边栏菜单,使用递归组件渲染多级菜单结构。菜单数据建议存储在Vuex中,与路由表保持同步。

vue 实现权限管理

// store/modules/permission.js
function filterAsyncRoutes(routes, roles) {
  const res = []
  routes.forEach(route => {
    const tmp = { ...route }
    if (hasPermission(roles, tmp)) {
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, roles)
      }
      res.push(tmp)
    }
  })
  return res
}

按钮级权限控制

通过自定义指令v-permission实现按钮粒度的权限控制,没有权限的按钮会被自动移除或禁用。

// directives/permission.js
export default {
  inserted(el, binding, vnode) {
    const { value } = binding
    const roles = store.getters.roles
    if (value && value instanceof Array) {
      const permissionRoles = value
      const hasPermission = roles.some(role => {
        return permissionRoles.includes(role)
      })
      if (!hasPermission) {
        el.parentNode && el.parentNode.removeChild(el)
      }
    } else {
      throw new Error(`需要指定权限数组`)
    }
  }
}

API请求鉴权

在axios拦截器中自动携带token,后端接口根据token进行权限验证。对于403状态码统一跳转到无权限页面。

vue 实现权限管理

// utils/request.js
service.interceptors.request.use(
  config => {
    if (store.getters.token) {
      config.headers['Authorization'] = `Bearer ${getToken()}`
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

service.interceptors.response.use(
  response => {
    const res = response.data
    if (res.code !== 200) {
      if (res.code === 403) {
        MessageBox.confirm('权限不足', '提示', {
          type: 'warning'
        })
      }
      return Promise.reject(new Error(res.message || 'Error'))
    } else {
      return res
    }
  }
)

权限数据持久化

使用vuex-persistedstate插件将权限数据持久化到localStorage,避免刷新后丢失权限状态。敏感数据建议加密存储。

// store/index.js
import createPersistedState from 'vuex-persistedstate'
export default new Vuex.Store({
  plugins: [
    createPersistedState({
      key: 'auth',
      paths: ['user.token', 'user.roles']
    })
  ]
})

服务端权限校验

前端权限控制只是用户体验优化,必须在服务端进行最终权限验证。RBAC模型是常见解决方案,包含用户-角色-权限三层关系。

-- 数据库表结构示例
CREATE TABLE `sys_user` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL,
  `password` varchar(100) NOT NULL
);

CREATE TABLE `sys_role` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL
);

CREATE TABLE `sys_permission` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `perm` varchar(50) NOT NULL,
  `description` varchar(100) DEFAULT NULL
);

标签: 权限vue
分享给朋友:

相关文章

在线脑图 vue 实现

在线脑图 vue 实现

在线脑图 Vue 实现方案 使用开源库实现 推荐使用 mind-elixir 或 jsmind 这类开源库,它们专为脑图设计且支持 Vue 集成。 安装依赖: npm install mind-e…

vue实现点击旋转轮盘

vue实现点击旋转轮盘

实现点击旋转轮盘效果 在Vue中实现点击旋转轮盘效果,可以通过CSS动画和Vue的数据绑定结合完成。以下是一个完整的实现方案: 准备工作 需要安装Vue.js环境,可以通过CDN引入或使用Vue C…

vue computed 实现

vue computed 实现

computed 的基本用法 在 Vue 中,computed 用于声明计算属性,这些属性基于响应式依赖进行缓存。只有当依赖发生变化时,计算属性才会重新计算。 new Vue({ data: {…

vue实现注销

vue实现注销

实现用户注销功能 在Vue应用中实现用户注销功能通常涉及清除用户会话、重置应用状态并跳转到登录页面。以下是具体实现方法: 清除用户认证信息 使用Vuex或Pinia管理用户状态时,需在注销时重置存储…

vue实现白板

vue实现白板

Vue实现白板功能 使用Vue实现白板功能可以通过HTML5的Canvas API结合Vue的响应式特性来完成。以下是实现白板功能的关键步骤: 安装依赖 在Vue项目中安装必要的依赖,如vue-dr…

vue 实现穿透

vue 实现穿透

Vue 样式穿透的实现方法 在 Vue 中,样式穿透通常指在带有 scoped 属性的样式块中,强制影响子组件的样式。以下是几种常见的实现方式: 使用 >>> 或 /deep/ 选…