You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Vue.js动态角色与路由的权限验证实现方案咨询

Vue.js 动态角色-路由权限验证方案

嘿,这个动态角色分配路由的需求我之前在项目里碰到过,刚好可以给你分享一套可行的实现思路,核心是后端控权限、前端做拦截+动态路由加载——毕竟前端的权限拦截只能做体验优化,真正的安全校验还得靠后端接口把关。

一、先理清楚核心数据逻辑

因为角色和路由都是用户可动态配置的,绝对不能在前端硬编码路由的角色权限。建议让后端返回两个关键信息:

  • 当前用户的角色列表(比如 ["管理员", "内容运营"]
  • 该用户可访问的路由配置列表(包含路由的pathnamecomponent路径、meta等信息)

举个后端返回的路由示例:

[
  {
    "path": "/dashboard",
    "name": "Dashboard",
    "component": "views/Dashboard.vue",
    "meta": { "title": "仪表盘" }
  },
  {
    "path": "/content-manage",
    "name": "ContentManage",
    "component": "views/ContentManage.vue",
    "meta": { "title": "内容管理", "allowedRoles": ["内容运营", "管理员"] }
  }
]

二、动态加载可访问路由

登录成功后,我们需要把后端返回的路由转换成Vue Router能识别的格式,动态添加到路由实例中,同时把这些信息存在本地(比如localStorage),避免页面刷新后丢失权限配置。

// 登录成功后的处理逻辑
async function handleLoginSuccess(token) {
  // 存储token用于后续接口鉴权
  localStorage.setItem('token', token);
  
  // 调用接口获取用户权限信息
  const { data } = await api.get('/api/user/permission');
  const { userRoles, accessibleRoutes } = data;
  
  // 存储角色和路由信息到本地
  localStorage.setItem('userRoles', JSON.stringify(userRoles));
  localStorage.setItem('accessibleRoutes', JSON.stringify(accessibleRoutes));
  
  // 将后端返回的路由转换成Vue Router可用的格式(处理组件按需加载)
  const formattedRoutes = accessibleRoutes.map(route => ({
    ...route,
    component: () => import(`../${route.component}`)
  }));
  
  // 动态添加路由到路由实例
  formattedRoutes.forEach(route => {
    router.addRoute(route);
  });
  
  // 跳转到首页或者用户原本要访问的页面
  router.push('/');
}

三、全局路由守卫做权限拦截

router/index.js里配置全局前置守卫,除了验证用户是否登录,还要校验当前路由是否在用户的可访问范围内:

router.beforeEach(async (to, from, next) => {
  // 1. 先验证是否已登录
  const isAuthenticated = !!localStorage.getItem('token');
  if (!isAuthenticated && to.path !== '/login') {
    return next('/login'); // 未登录则强制跳登录页
  }
  if (isAuthenticated && to.path === '/login') {
    return next('/'); // 已登录则直接跳过登录页
  }

  // 2. 验证当前路由是否有权访问
  const accessibleRoutes = JSON.parse(localStorage.getItem('accessibleRoutes')) || [];
  const userRoles = JSON.parse(localStorage.getItem('userRoles')) || [];

  // 两种校验方式选其一即可:
  // 方式A:检查当前路由是否在后端返回的可访问列表中(推荐,权限边界更清晰)
  const isRouteAllowed = accessibleRoutes.some(route => route.path === to.path);
  
  // 方式B:检查路由meta.allowedRoles是否包含用户角色(适合细粒度权限控制)
  // const isRouteAllowed = to.meta?.allowedRoles 
  //   ? to.meta.allowedRoles.some(role => userRoles.includes(role)) 
  //   : true; // 未配置allowedRoles的路由默认允许访问

  if (!isRouteAllowed) {
    return next('/403'); // 无权限则跳403页面
  }

  next();
});

四、处理页面刷新的情况

页面刷新后,Vue Router的动态路由会丢失,所以需要在应用初始化时重新加载权限路由:

// main.js
async function initApp() {
  const token = localStorage.getItem('token');
  if (token) {
    // 重新读取本地存储的路由并添加到路由实例
    const accessibleRoutes = JSON.parse(localStorage.getItem('accessibleRoutes')) || [];
    const formattedRoutes = accessibleRoutes.map(route => ({
      ...route,
      component: () => import(`../${route.component}`)
    }));
    formattedRoutes.forEach(route => router.addRoute(route));
    
    // 刷新后确保当前路由能正确匹配(避免出现404)
    router.push(router.currentRoute.fullPath);
  }

  // 初始化Vue实例
  new Vue({
    router,
    store,
    render: h => h(App)
  }).$mount('#app');
}

initApp();

五、关键注意事项

  • 后端兜底验证:前端的路由拦截只是提升用户体验,所有接口都必须在后端做角色权限校验,防止非法请求。
  • 避免硬编码角色:因为角色是用户动态创建的,前端不要写死任何角色名称,所有角色判断都依赖后端返回的数据。
  • 路由组件按需加载:动态路由的component一定要用按需加载,避免打包体积过大影响性能。

内容的提问来源于stack exchange,提问作者Rasik

火山引擎 最新活动