likes
comments
collection
share

一篇搞懂Vue项目里的权限控制

作者站长头像
站长
· 阅读数 15

我正在参加「掘金·启航计划」

菜单权限控制

在Vue中需要根据用户的权限信息动态生成菜单,并在路由级别进行权限验证,以实现菜单路由权限控制,具体可以按照以下步骤进行:

1. 定义菜单数据结构

首先,定义一个菜单数据结构,包含菜单项的名称、路径和权限标识等信息。你可以根据项目需要,将菜单数据存储在一个数组或对象中。

const menuData = [
    {
    name: 'Home',
    path: '/home',
    permission: 'home:view' // 权限标识
    },
    {
    name: 'Products',
    path: '/products',
    permission: 'products:view'
    },
    {
    name: 'Orders',
    path: '/orders',
    permission: 'orders:view'
    },
    // 其他菜单项...
    ];

2. 获取用户权限

在用户登录或应用初始化时,获取当前用户的权限信息,并将其保存在本地,例如使用Vuex或localStorage。以下是一个示例代码实现:

 // 在登录成功后的处理逻辑中 
 // 假设从服务器端获取到的用户权限信息为 userPermissions 
 // 存储到Vuex 
 this.$store.commit('setUserPermissions', userPermissions); 
 // 或存储到localStorage 
 localStorage.setItem('userPermissions', JSON.stringify(userPermissions));

在上述代码中,假设从服务器端获取到了用户的权限信息 userPermissions。你可以使用Vuex的commit方法来触发一个mutation,将权限信息存储到Vuex的状态管理中。或者,你也可以将权限信息通过localStoragesetItem方法存储到本地存储中,通常需要将其转换为字符串格式。

在Vuex中存储用户权限的示例代码如下:

// 在Vuex的store模块中定义mutations和state 
// store.js 
import Vue from 'vue'; 
import Vuex from 'vuex'; 
Vue.use(Vuex); 
const store = new Vuex.Store({ 
    state: { 
        userPermissions: [] // 初始状态为空数组 
    },
    mutations: { 
        setUserPermissions(state, permissions) 
            { 
                state.userPermissions = permissions; 
            } 
        } 
       }); 
 export default store;

在以上示例中,我们定义了一个名为userPermissions的状态,并在setUserPermissions mutation中将传入的权限信息赋值给该状态。

使用localStorage存储用户权限的示例代码如下:

 // 在登录成功后的处理逻辑中 
 // 假设从服务器端获取到的用户权限信息为 userPermissions 
 localStorage.setItem('userPermissions', JSON.stringify(userPermissions));

在上述代码中,我们使用localStoragesetItem方法将用户权限信息存储为一个字符串。这样,权限信息将被保存在浏览器的本地存储中。

3. 根据权限生成菜单

在菜单组件中,根据用户的权限信息,遍历菜单数据,根据用户拥有的权限标识来生成对应的可访问菜单项。可以使用Vue的条件渲染指令,如v-ifv-show,来根据用户的权限动态地显示或隐藏菜单项。以下是一个示例代码实现:

<template> 
    <div> 
        <ul> 
            <li v-for="item in menuData" :key="item.path" v-show="hasPermission(item.permission)"> 
            <router-link :to="item.path">{{ item.name }}</router-link> 
            </li> 
         </ul> 
     </div> 
 </template> 
 <script> 
     export default { 
         computed: { 
             menuData() { 
                 // 获取菜单数据 
                 return menuData; 
             } }, 
         methods: { 
             hasPermission(permission) 
                 { 
                     // 判断用户是否有权限 
                     // 假设权限信息存储在this.$store.state.user.permissions中 
                     const userPermissions = this.$store.state.user.permissions; 
                     return userPermissions.includes(permission); 
                 } 
          } 
     } 
</script>

路由守卫权限控制

在Vue Router中,根据用户的权限信息配置路由。在路由配置中,为每个需要进行权限控制的路由设置相应的权限标识。在导航守卫(Navigation Guards)中,对用户的访问进行权限验证。根据用户的权限信息和路由配置,决定是否允许用户访问该路由。

  • 全局前置守卫(beforeEach):在全局前置守卫中,根据当前路由的权限标识和用户的权限信息,进行权限验证。如果用户没有权限访问当前路由,可以重定向到登录页面或显示无权限的提示信息。
  • 路由级别的元信息(meta):在路由配置中,使用元信息(meta)字段来存储路由的权限标识。通过在导航守卫中获取路由的元信息,进行权限验证和控制。

Vue Router配置: 根据菜单数据的权限标识,配置Vue Router的路由,并在导航守卫中进行权限验证。

import Vue from 'vue'; 
import Router from 'vue-router'; 
Vue.use(Router); 
const router = new Router({ 
    routes: [ 
        { 
            path: '/home', 
            component: Home, 
            meta: { permission: 'home:view' } // 路由权限标识 
        }, 
        { 
             path: '/products', 
             component: Products, 
             meta: { permission: 'products:view' } 
         }, 
         { 
             path: '/orders', 
             component: Orders, 
             meta: { permission: 'orders:view' } 
          }, 
          // 其他路由配置... 
       ] 
 }); 
 router.beforeEach((to, from, next) => { 
     const userPermissions = store.state.user.permissions; 
     const requiredPermission = to.meta.permission; 
         if (requiredPermission && !userPermissions.includes(requiredPermission)) { 
             // 没有权限,重定向到登录页面或显示无权限提示 
             next('/login');
             // 或者显示无权限提示页面 
             // next('/no-permission'); 
          } else { 
              next(); 
           } 
    });
export default router;

组建级按钮的权限控制

在需求进行按钮级别权限控制的Vue组件中,可以使用指令或计算属性来判断用户是否具有对应的权限,从而决定按钮的显示与否或可操作性。

使用自定义指令:

<template> 
    <button v-permission="'user:create'">Create User</button> </template> <script> 
export default { 
    directives: { 
        permission: { 
            inserted(el, binding) 
                { 
                    const userPermissions = this.$store.state.user.permissions; 
                    const requiredPermission = binding.value; 
                    if (!userPermissions.includes(requiredPermission)) { 
                          el.style.display = 'none'; // 或禁用按钮等操作 
                     } 
                } 
            } 
         } 
     } 
 </script>

使用计算属性:

<template> 
       <button v-if="hasPermission('user:create')">Create User</button> </template> 
<script> 
        export default { 
            methods: { 
                hasPermission(permission) { 
                    const userPermissions = this.$store.state.user.permissions; 
                    return userPermissions.includes(permission); 
             } 
        } 
     } 
</script>

在上述示例中,我们使用了自定义指令v-permission和计算属性hasPermission来判断用户是否具有user:create的权限。如果用户没有该权限,按钮将被隐藏或禁用。

需要注意的是,在以上示例中,我们假设用户的权限信息存储在Vuex的state.user.permissions中,你可以根据实际情况进行相应的调整。

API权限管理

有时候需要根据用户的权限信息,限制用户对后端API的访问。可以在前端发送API请求前进行权限判断,并根据权限信息决定是否发送请求或进行其他处理。示例代码如下:

axios.interceptors.request.use((config) => { 
    // 判断用户是否有权限访问API 
    if (!hasPermission(config.url)) { 
        // 不允许访问,取消请求或其他处理方式 
        return Promise.reject(new Error('无权限访问该API')); 
   } 
   return config; 
   }, 
   (error) => { 
    return Promise.reject(error); 
   });

动态路由权限

在某些情况下,权限可能会根据用户角色的不同而动态生成路由。这可以通过在登录或权限更新时,根据用户权限信息动态生成路由配置来实现。例如,可以将权限信息映射为路由对象,然后将这些动态生成的路由配置添加到路由器中。示例代码如下:

// 动态生成路由配置 
    function generateRoutes(permissionList) { 
        const routes = []; 
        permissionList.forEach(permission => { 
            const route = { 
                path: permission.path, 
                component: () => import(`@/views/${permission.component}`), 
                meta: { // 其他路由元信息 } }; 
                routes.push(route); 
            }); 
        return routes; 
      } 
      // 添加动态路由 
      router.addRoutes(generateRoutes(permissionList));

角色管理

有时需要根据用户的角色来管理权限。可以为每个角色分配一组权限,并根据用户所属的角色来判断其是否有权访问特定的功能。这可以通过在用户登录后获取用户的角色信息,并在需要进行权限判断时根据角色来进行处理。示例代码如下:

1.定义角色和权限:

   // 角色列表 
   const roles = [ 
       { id: 1, name: '管理员' }, 
       { id: 2, name: '普通用户' } 
   ]; 
   // 权限列表 
   const permissions = [ 
       { id: 1, name: '创建用户', role: '管理员' }, 
       { id: 2, name: '编辑用户', role: '管理员' }, 
       { id: 3, name: '查看用户', role: '管理员' }, 
       { id: 4, name: '查看用户列表', role: '普通用户' } 
   ];

2.获取用户角色:

    function getUserRoles(userId) { 
        // 根据用户ID获取用户所属的角色列表 
        // 返回一个包含角色名称的数组 
   }

3.权限判断:

   function hasPermission(permission, userId) 
   { 
       const userRoles = getUserRoles(userId); 
       // 根据用户角色判断是否具有权限 
       return permissions.some(p => p.name === permission && userRoles.includes(p.role)); 
    }

在这个示例中,我们定义了角色列表和权限列表。通过getUserRoles()函数获取用户的角色列表,然后使用hasPermission()函数来判断用户是否具有特定权限。hasPermission()函数会检查用户角色是否包含相应权限的角色,如果包含则返回true,否则返回false

使用自定义指令

v-permission:根据用户权限控制元素的显示或隐藏。

// 假设有一个用户权限列表,存储了用户可以访问的页面或功能
const userPermissions = ['home', 'about', 'profile', 'setting']

// 全局注册
Vue.directive('permission', {
  mounted: (el, binding) => {
    // 获取指令绑定的值,即需要的权限
    let permission = binding.value
    // 判断用户权限列表中是否包含该权限
    if (!userPermissions.includes(permission)) {
      // 如果不包含,就移除元素
      el.parentNode.removeChild(el)
    }
  }
})

  // 使用,可以给任意元素添加 v-permission 指令,根据需要的权限来控制显示或隐藏。
  <a v-permission="'home'" href="/home">首页</a>
  <a v-permission="'about'" href="/about">关于</a>
  <a v-permission="'profile'" href="/profile">个人中心</a>
  <a v-permission="'setting'" href="/setting">设置</a>

以上是在实际应用中,整理出的权限相关场景及解决思路和代码示例,示例只是一个简单的演示,实际情况下可能需要更复杂的角色和权限管理方案。