vue如何实现权限控制
路由权限控制
使用vue-router的全局守卫beforeEach,结合用户角色动态过滤路由表。定义静态路由(如登录页)和动态路由(需权限访问的路由),通过addRoutes方法动态添加符合条件的路由。
// router/index.js
const router = new VueRouter({...})
const whiteList = ['/login'] // 白名单
router.beforeEach((to, from, next) => {
if (hasToken()) {
if (to.path === '/login') next('/')
else {
const hasRoles = store.getters.roles.length > 0
if (hasRoles) next()
else {
try {
const roles = await store.dispatch('user/getUserInfo')
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
router.addRoutes(accessRoutes)
next({ ...to, replace: true })
} catch (error) {
next(`/login?redirect=${to.path}`)
}
}
}
} else {
if (whiteList.includes(to.path)) next()
else next(`/login?redirect=${to.path}`)
}
})
按钮级权限控制
通过自定义指令v-permission实现。在全局注册指令,根据用户权限动态显示/隐藏按钮。
// directives/permission.js
function checkPermission(el, binding) {
const { value } = binding
const roles = store.getters.roles
if (value && value instanceof Array) {
if (value.length > 0) {
const hasPermission = roles.some(role => value.includes(role))
if (!hasPermission) el.parentNode && el.parentNode.removeChild(el)
}
} else {
throw new Error(`需要指定权限数组,如v-permission="['admin']"`)
}
}
export default {
inserted(el, binding) {
checkPermission(el, binding)
},
update(el, binding) {
checkPermission(el, binding)
}
}
菜单权限控制
根据用户角色过滤菜单数据。在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
}
接口权限控制
在axios拦截器中添加请求头携带token,服务端验证token有效性。对于无权限的请求返回401状态码,前端统一跳转登录页。
// 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 => response.data,
error => {
if (error.response.status === 401) {
MessageBox.confirm('登录已过期', '重新登录', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
store.dispatch('user/resetToken').then(() => {
location.reload()
})
})
}
return Promise.reject(error)
}
)
权限数据持久化
使用localStorage或sessionStorage存储token和基础用户信息,避免页面刷新后权限丢失。注意敏感信息需要加密处理。
// utils/auth.js
export function getToken() {
return localStorage.getItem('token')
}
export function setToken(token) {
return localStorage.setItem('token', token)
}
export function removeToken() {
return localStorage.removeItem('token')
}






