项目中使用了全局权限管理,请详细描述如何通过Vue Router的路由守卫来实现全局权限控制?

在 Vue 项目中,全局权限控制 的核心思路是:通过路由守卫拦截所有路由跳转,校验用户权限,无权限则拦截跳转至登录页 / 403 页

我会从核心概念、实现步骤、完整代码、细节优化四个维度,给你最实用、可直接落地的方案。

一、核心概念

  1. Vue Router 全局前置守卫router.beforeEach
    • 所有路由跳转都会先经过这个守卫,是实现全局权限控制的唯一入口
  1. 权限判断逻辑
    • 是否登录?
    • 路由是否需要权限?
    • 用户角色 / 权限是否匹配当前路由?
  1. 路由元信息 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')
}

四、权限控制执行流程

  1. 用户访问任意页面 → 触发 beforeEach
  2. 判断路由是否需要权限(requireAuth
  3. 不需要 → 直接放行
  4. 需要 → 检查是否登录
    • 未登录 → 跳转登录页
    • 已登录 → 检查角色权限
      • 角色匹配 → 放行
      • 不匹配 → 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. 动态路由(进阶)

后端返回权限路由 → 前端动态添加路由,比单纯拦截更安全。


六、总结

  1. 全局权限控制 = 路由守卫 beforeEach + 路由 meta 标记 + 用户权限判断
  2. 核心拦截逻辑:是否需要登录 → 是否登录 → 是否拥有角色权限
  3. 代码可直接复制到项目中使用,适配绝大多数中后台系统
  4. 简单项目用本地权限判断,大型项目用动态路由更安全

这就是企业级 Vue 项目最标准、最常用的全局权限控制方案。

相关推荐
做前端的娜娜子2 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅2 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni3 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学4 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端
赵庆明老师4 小时前
Vben精讲:21-详解web-antd:tsconfig.json
前端·json·vim
wc884 小时前
微软EDGE浏览器功能学习
前端·学习·edge
Csvn5 小时前
🎯 原生 `<dialog>` 元素:终于可以扔掉一半的自定义弹窗组件了?
前端
Csvn5 小时前
🎨 CSS @layer:用「层叠优先级」终结样式打架的世纪难题
前端
小罗水6 小时前
第17章 后台管理端与演示支持
javascript·vue.js·ecmascript