项目中使用了全局权限管理,请详细描述如何通过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 项目最标准、最常用的全局权限控制方案。

相关推荐
雪铃儿1 小时前
Shorebird 之外,Flutter Android 热更新还有什么选择
android·前端
李剑一1 小时前
前端必看 | Vue 刷新页面,生命周期钩子直接 "罢工",原来问题在这?90% 开发者都栽过!
前端·vue.js
閞杺哋笨小孩1 小时前
域名驱动多租户入驻:后台配置 + 前端解析
前端·vue.js
TeamDev1 小时前
在 Excel 加载项中嵌入 Web 视图
前端·后端·.net
悠哉摸鱼大王1 小时前
cesium学习(一)-基本概念
前端·cesium
LinDaiDai_霖呆呆1 小时前
大白话介绍大模型的一些底层原理,看完终于能跟人聊两句了
前端·人工智能·面试
悠哉摸鱼大王1 小时前
cesium学习(二)-地图地形
前端·cesium
青山师2 小时前
【AI热点资讯】5月10日AI热点:Cloudflare裁员1100人、Musk庭审第二周回顾、OpenAI发布Codex Chrome插件
前端·人工智能·chrome·ai·ai热点
阿赛工作室2 小时前
AI时代WEB开发人员生存与发展报告
前端·人工智能·node.js