一篇搞懂Vue项目里的权限控制
我正在参加「掘金·启航计划」
菜单权限控制
在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的状态管理中。或者,你也可以将权限信息通过localStorage
的setItem
方法存储到本地存储中,通常需要将其转换为字符串格式。
在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));
在上述代码中,我们使用localStorage
的setItem
方法将用户权限信息存储为一个字符串。这样,权限信息将被保存在浏览器的本地存储中。
3. 根据权限生成菜单
在菜单组件中,根据用户的权限信息,遍历菜单数据,根据用户拥有的权限标识来生成对应的可访问菜单项。可以使用Vue的条件渲染指令,如v-if
或v-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>
以上是在实际应用中,整理出的权限相关场景及解决思路和代码示例,示例只是一个简单的演示,实际情况下可能需要更复杂的角色和权限管理方案。
转载自:https://juejin.cn/post/7241846256288104504