各位靓仔靓女,晚上好!我是今天的主讲人,咱们今天来聊聊 Vue 项目中权限管理那些事儿,保证让你的项目安全得像个保险箱,而且代码写起来还倍儿爽。
一、权限管理:为什么要搞事情?
先问大家一个问题,你家的门锁是摆设吗?当然不是!权限管理就像你家门锁,防止不该进的人进来,不该看的东西被看到,不该搞的事情被搞了。
在一个系统中,不同用户角色应该有不同的权限。比如,管理员可以查看所有数据,编辑所有内容,而普通用户可能只能查看自己的数据,修改自己的密码。
二、权限管理的分类:你想要哪种姿势?
权限管理不是只有一种玩法,常见的有以下几种:
- 路由权限: 决定用户能访问哪些页面。
- 按钮权限: 决定用户能点击哪些按钮,能执行哪些操作。
- 数据权限: 决定用户能看到哪些数据,比如只能看到自己部门的数据。
三、技术选型:磨刀不误砍柴工
- Vue Router: 路由管理,必须滴。
- Vuex/Pinia: 状态管理,用来存放用户角色、权限等信息。
- axios/fetch: 数据请求,跟后端大哥沟通的桥梁。
四、权限管理的核心思路:三步走战略
- 登录认证: 验证用户身份,获取用户角色和权限信息。
- 权限判断: 根据用户角色和权限信息,判断用户是否有权访问某个路由、按钮或数据。
- 权限控制: 根据判断结果,控制页面元素的显示和隐藏,阻止用户操作。
五、路由权限:守好进门的第一道关
-
定义路由元信息: 在路由配置中,添加
meta
字段,用于标识该路由需要的权限。// router/index.js import Vue from 'vue' import VueRouter from 'vue-router' import Home from '../views/Home.vue' import Admin from '../views/Admin.vue' Vue.use(VueRouter) const routes = [ { path: '/', name: 'Home', component: Home }, { path: '/admin', name: 'Admin', component: Admin, meta: { requiresAuth: true, // 需要登录 roles: ['admin'] // 需要管理员权限 } }, { path: '/login', name: 'Login', component: () => import('../views/Login.vue') }, { path: '/about', name: 'About', // route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited. component: () => import(/* webpackChunkName: "about" */ '../views/About.vue') } ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) export default router
这里
requiresAuth: true
表示需要登录才能访问,roles: ['admin']
表示需要管理员角色才能访问。 -
全局路由守卫: 使用
router.beforeEach
监听路由变化,进行权限判断。// router/index.js router.beforeEach((to, from, next) => { const isAuthenticated = localStorage.getItem('token'); // 模拟token存在表示已登录 const userRole = localStorage.getItem('role'); // 模拟用户角色 if (to.meta.requiresAuth) { if (!isAuthenticated) { // 未登录,跳转到登录页面 next({ name: 'Login' }); } else { if (to.meta.roles && !to.meta.roles.includes(userRole)) { // 角色不匹配,跳转到 403 页面或者提示无权限 alert('没有权限访问该页面'); next({ name: 'Home' }); // 跳转到首页或者403页面 } else { // 权限匹配,允许访问 next(); } } } else { // 不需要权限的页面,直接允许访问 next(); } });
这段代码做了三件事:
- 判断路由是否需要登录。
- 如果需要登录,判断用户是否已登录。
- 如果已登录,判断用户角色是否匹配。
-
登录逻辑: 在登录页面,验证用户身份,获取用户角色和权限信息,并存储到 Vuex/Pinia 或 localStorage 中。
// Login.vue export default { data() { return { username: '', password: '' }; }, methods: { login() { // 模拟登录,实际需要调用后端接口 if (this.username === 'admin' && this.password === '123') { localStorage.setItem('token', 'admin_token'); // 模拟token localStorage.setItem('role', 'admin'); // 模拟用户角色 this.$router.push({ name: 'Admin' }); } else if (this.username === 'user' && this.password === '123'){ localStorage.setItem('token', 'user_token'); // 模拟token localStorage.setItem('role', 'user'); // 模拟用户角色 this.$router.push({ name: 'Home' }); } else { alert('用户名或密码错误'); } } } };
这里模拟了登录逻辑,实际项目中需要调用后端接口进行验证。
六、按钮权限:防止手贱党乱点
-
自定义指令: 定义一个自定义指令,用于判断按钮是否需要权限,并控制按钮的显示和隐藏。
// directives/permission.js import Vue from 'vue'; Vue.directive('permission', { inserted: function (el, binding) { const requiredPermission = binding.value; // 获取指令绑定的权限标识 const userPermissions = localStorage.getItem('permissions')?.split(',') || []; // 模拟用户权限列表 if (!userPermissions.includes(requiredPermission)) { el.parentNode.removeChild(el); // 移除元素 // 或者 el.style.display = 'none'; // 隐藏元素 } } });
这段代码做了两件事:
- 获取按钮需要的权限标识。
- 判断用户是否拥有该权限,如果没有,则移除或隐藏按钮。
-
使用指令: 在模板中使用自定义指令,绑定按钮需要的权限标识。
<template> <div> <button v-permission="'create'">新建</button> <button v-permission="'edit'">编辑</button> <button v-permission="'delete'">删除</button> </div> </template> <script> export default { mounted() { // 模拟权限信息 const role = localStorage.getItem('role'); let permissions = []; if(role === 'admin'){ permissions = ['create', 'edit', 'delete', 'view']; } else { permissions = ['view']; } localStorage.setItem('permissions', permissions.join(',')); } }; </script>
这里,
v-permission="'create'"
表示只有拥有create
权限的用户才能看到 “新建” 按钮。 -
权限数据: 权限信息通常从后端获取,并存储到 Vuex/Pinia 或 localStorage 中。
七、数据权限:保护你的敏感数据
- 后端配合: 数据权限的实现,需要后端的配合。后端需要根据用户角色和权限信息,过滤返回的数据。
-
前端处理: 前端接收到数据后,可以根据用户角色和权限信息,进行二次过滤或隐藏。
// 假设后端返回的数据如下: const data = [ { id: 1, name: '张三', department: '研发部', salary: 10000 }, { id: 2, name: '李四', department: '销售部', salary: 8000 }, { id: 3, name: '王五', department: '财务部', salary: 12000 } ]; // 前端根据用户角色进行过滤 const userRole = localStorage.getItem('role'); let filteredData = data; if (userRole === '普通用户') { // 普通用户只能看到自己的数据 filteredData = data.filter(item => item.name === '李四'); // 假设李四是当前用户 } else if (userRole === '部门经理') { // 部门经理只能看到自己部门的数据 filteredData = data.filter(item => item.department === '销售部'); } // 显示过滤后的数据 console.log(filteredData);
这里,我们根据用户角色,对数据进行了过滤。
八、权限管理表格:一目了然
为了更清晰地展示不同角色拥有的权限,我们可以使用表格来管理。
角色 | 路由权限 | 按钮权限 | 数据权限 |
---|---|---|---|
管理员 | 所有 | 所有 | 所有数据 |
普通用户 | 首页 | 查看 | 只能看到自己的数据 |
部门经理 | 首页、部门管理 | 查看、编辑 | 只能看到自己部门的数据 |
九、代码示例:一个简单的权限管理 Demo
为了方便大家理解,我写了一个简单的权限管理 Demo,包含路由权限和按钮权限。
// App.vue
<template>
<div id="app">
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/admin" v-if="$route.meta.requiresAuth">Admin</router-link> |
<router-link to="/login">Login</router-link>
</nav>
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
};
</script>
// Home.vue
<template>
<div>
<h1>Home</h1>
<p>Welcome to the Home page!</p>
<button v-permission="'view'">查看</button>
</div>
</template>
<script>
export default {
mounted() {
// 模拟权限信息
const role = localStorage.getItem('role');
let permissions = [];
if(role === 'admin' || role === 'user'){
permissions = ['view'];
}
localStorage.setItem('permissions', permissions.join(','));
}
};
</script>
// Admin.vue
<template>
<div>
<h1>Admin</h1>
<p>Welcome to the Admin page!</p>
<button v-permission="'create'">新建</button>
<button v-permission="'edit'">编辑</button>
<button v-permission="'delete'">删除</button>
</div>
</template>
<script>
export default {
mounted() {
// 模拟权限信息
const role = localStorage.getItem('role');
let permissions = [];
if(role === 'admin'){
permissions = ['create', 'edit', 'delete', 'view'];
}
localStorage.setItem('permissions', permissions.join(','));
}
};
</script>
// Login.vue
<template>
<div>
<h1>Login</h1>
<input type="text" v-model="username" placeholder="Username">
<input type="password" v-model="password" placeholder="Password">
<button @click="login">Login</button>
</div>
</template>
<script>
export default {
data() {
return {
username: '',
password: ''
};
},
methods: {
login() {
// 模拟登录,实际需要调用后端接口
if (this.username === 'admin' && this.password === '123') {
localStorage.setItem('token', 'admin_token'); // 模拟token
localStorage.setItem('role', 'admin'); // 模拟用户角色
this.$router.push({ name: 'Admin' });
} else if (this.username === 'user' && this.password === '123'){
localStorage.setItem('token', 'user_token'); // 模拟token
localStorage.setItem('role', 'user'); // 模拟用户角色
this.$router.push({ name: 'Home' });
}
else {
alert('用户名或密码错误');
}
}
}
};
</script>
十、注意事项:细节决定成败
- 权限标识: 权限标识要统一规范,方便管理。
- 权限缓存: 权限信息可以缓存到 localStorage 中,避免每次都从后端获取。
- 后端安全: 后端也要进行权限验证,防止前端绕过权限控制。
- 用户体验: 权限不足时,要给出友好的提示,避免用户困惑。
十一、总结:权限管理,安全第一
权限管理是每个系统都必须考虑的问题,它关系到系统的安全和数据的隐私。希望今天的分享能够帮助大家更好地理解和实现 Vue 项目中的权限管理。
记住,代码的世界里,安全永远是第一位的!
好了,今天的讲座就到这里,大家有什么问题可以提问。