在 Vue 项目中,全局权限控制 的核心思路是:通过路由守卫拦截所有路由跳转,校验用户权限,无权限则拦截跳转至登录页 / 403 页。
我会从核心概念、实现步骤、完整代码、细节优化四个维度,给你最实用、可直接落地的方案。
一、核心概念
- Vue Router 全局前置守卫 :
router.beforeEach
-
- 所有路由跳转都会先经过这个守卫,是实现全局权限控制的唯一入口
- 权限判断逻辑
-
- 是否登录?
- 路由是否需要权限?
- 用户角色 / 权限是否匹配当前路由?
- 路由元信息
meta
-
- 在路由配置中标记:是否需要登录、所需权限 / 角色
二、完整实现步骤
步骤 1:配置路由表(标记权限)
给需要权限控制的路由添加 meta 元信息:
javascript
// router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import Login from '@/views/Login'
import Home from '@/views/Home'
import Admin from '@/views/Admin'
import NotFound from '@/views/NotFound'
Vue.use(Router)
const routes = [
{
path: '/login',
name: 'Login',
component: Login,
meta: {
requireAuth: false // 不需要登录
}
},
{
path: '/',
name: 'Home',
component: Home,
meta: {
requireAuth: true // 需要登录才能访问
}
},
{
path: '/admin',
name: 'Admin',
component: Admin,
meta: {
requireAuth: true,
roles: ['admin'] // 仅管理员可访问
}
},
{
path: '*',
component: NotFound
}
]
const router = new Router({
routes
})
// 👇 路由守卫写在这里
export default router
步骤 2:封装用户权限工具方法
用于获取登录状态、用户角色、token,通常存在 localStorage/Vuex/Pinia 中:
javascript
// utils/auth.js
// 获取token
export function getToken() {
return localStorage.getItem('token')
}
// 获取用户角色
export function getUserRole() {
return localStorage.getItem('userRole') || ''
}
// 判断是否登录
export function isLogin() {
return !!getToken()
}
步骤 3:编写全局路由守卫(核心)
这是权限控制的核心代码,直接加在路由文件中:
javascript
// 导入权限工具
import { isLogin, getUserRole } from '@/utils/auth'
// 全局前置守卫:所有路由跳转前执行
router.beforeEach((to, from, next) => {
// 1. 判断当前路由是否需要登录权限
if (to.meta.requireAuth) {
// 2. 判断用户是否已登录
if (isLogin()) {
// 3. 已登录 → 判断是否需要角色权限
if (to.meta.roles && to.meta.roles.length > 0) {
// 获取用户角色
const role = getUserRole()
// 检查用户角色是否在路由允许的角色中
if (to.meta.roles.includes(role)) {
// 有权限 → 放行
next()
} else {
// 无权限 → 跳转到403/首页
next('/403')
}
} else {
// 不需要角色,仅需登录 → 放行
next()
}
} else {
// 未登录 → 强制跳转到登录页,并记录跳转前的页面,登录后跳转回去
next(`/login?redirect=${to.fullPath}`)
}
} else {
// 不需要权限 → 直接放行
next()
}
})
三、完整可复制代码
1. 路由文件(router/index.js)
javascript
import Vue from 'vue'
import Router from 'vue-router'
import { isLogin, getUserRole } from '@/utils/auth'
// 页面组件
import Login from '@/views/Login'
import Home from '@/views/Home'
import Admin from '@/views/Admin'
import NotFound from '@/views/NotFound'
import Forbidden from '@/views/Forbidden'
Vue.use(Router)
const routes = [
{
path: '/login',
component: Login,
meta: { requireAuth: false }
},
{
path: '/',
component: Home,
meta: { requireAuth: true }
},
{
path: '/admin',
component: Admin,
meta: {
requireAuth: true,
roles: ['admin']
}
},
{
path: '/403',
component: Forbidden,
meta: { requireAuth: false }
},
{
path: '*',
component: NotFound
}
]
const router = new Router({
mode: 'history',
routes
})
// 全局路由守卫
router.beforeEach((to, from, next) => {
// 需要登录
if (to.meta.requireAuth) {
if (isLogin()) {
// 校验角色权限
if (to.meta.roles) {
const userRole = getUserRole()
if (to.meta.roles.includes(userRole)) {
next()
} else {
next('/403')
}
} else {
next()
}
} else {
// 未登录,跳转登录
next(`/login?redirect=${to.path}`)
}
} else {
// 不需要登录,直接放行
next()
}
})
export default router
2. 权限工具(utils/auth.js)
javascript
// 获取token
export function getToken() {
return localStorage.getItem('token')
}
// 获取用户角色
export function getUserRole() {
return localStorage.getItem('userRole')
}
// 是否登录
export function isLogin() {
return !!getToken()
}
// 登录后保存信息
export function saveAuth(token, role) {
localStorage.setItem('token', token)
localStorage.setItem('userRole', role)
}
// 退出登录清除信息
export function clearAuth() {
localStorage.removeItem('token')
localStorage.removeItem('userRole')
}
四、权限控制执行流程
- 用户访问任意页面 → 触发
beforeEach - 判断路由是否需要权限(
requireAuth) - 不需要 → 直接放行
- 需要 → 检查是否登录
-
- 未登录 → 跳转登录页
- 已登录 → 检查角色权限
-
-
- 角色匹配 → 放行
- 不匹配 → 403 无权限页面
-
五、高频优化点(生产环境必备)
1. 白名单配置
不需要登录的页面统一管理,避免每个路由都写 requireAuth: false
javascript
// 白名单
const whiteList = ['/login', '/403', '/register']
router.beforeEach((to, from, next) => {
if (whiteList.includes(to.path)) {
next()
return
}
// 其余走权限逻辑
})
2. 防止守卫死循环
确保登录页、403 页不被守卫拦截。
3. 结合 Vuex/Pinia 管理权限
把 token、角色、权限列表存在状态管理器中,更适合大型项目。
4. 动态路由(进阶)
后端返回权限路由 → 前端动态添加路由,比单纯拦截更安全。
六、总结
- 全局权限控制 = 路由守卫 beforeEach + 路由 meta 标记 + 用户权限判断
- 核心拦截逻辑:是否需要登录 → 是否登录 → 是否拥有角色权限
- 代码可直接复制到项目中使用,适配绝大多数中后台系统
- 简单项目用本地权限判断,大型项目用动态路由更安全
这就是企业级 Vue 项目最标准、最常用的全局权限控制方案。