vue 实现权限管理
路由权限控制
使用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中,与路由表保持同步。
// 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状态码统一跳转到无权限页面。
// 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
);






