vue登录权限管理

1.所需知识点

vue-router路由守卫

Vue Router 是 Vue.js 官方的路由管理器,在vue项中要想 实现登录拦截跳转功能,必然离不开vue-router,这里应用到一个主要知识点,vue-router中的导航 守卫,在开始实现功能之前建议大家仔细看一看这个 知识点。

导航守卫分为全局导航守卫,单独路由守卫和组件 独享的守卫,这里主要应用的是全局 导航守卫。

beforeEach((to,from,next)=>{ }) 这是全局 前置守卫

afterEach((to,from)) 这是全局后置守卫

to 表示 目标路由

from 表示当前离开的路由

next 简单来说就说下一步的意思,这里可以理解是向下执行,主要有以下三种用法,next() next(false) next(’/path’) 不多做解释了,官网解释的很全。

2.功能分析

1.用户通过账号密码登录,登录成功后台返回token,根据token获取权限信息。

2.router.js中路由分两部分,一部分是恒定路由,一部分是需要权限才能访问的异步加载路由,页面初始化时只加载恒定路由,注意404页面要放到最后声明,否则登录拦截后异步加载路由都会被拦截到404页面,异步加载路由的声明中可通过meta标签添加用户权限,这里设置的用户权限可通过$router.matched 获取。

3.vuex存储路由信息,导航栏的数据源从vuex中获取。获取到权限信息后调用vuex中的方法,判断权限,根据权限信息计算当前用户对应的全部路由信息,存储到vuex的state中。

4.permission.js中通过全局路由守卫对于不同登录和权限情况进行分析判断。

注意一:
roter.addRoutes()不可缺少,这一步是将路由变为用户可访问的路由。

注意二:
不能重复使用router.addRoutes()控制台会有警告 Duplicate named routes definition, 所以在每次通router.addRoutes()动态挂载的时候要判断是否已经获取了权限信息,已经有了路由。

一、登录情况分析

1.判断有无登录

2.有登录缓存的情况

跳转登录页     转到主页  next('/home')
跳转非登录页   正常跳转  next()

3.无登录缓存的情况

跳转登录页     正常跳转  next()
跳转非登录页    路由拦截 强制转到登录页  next('/login')

二、权限情况分析

1.判断用户是否已经根据token获取了权限信息

2.没有获取权限信息

获取权限信息
调用vuex中的方法计算当前权限可访问的路由表
动态添加可访问路由表

3.已经获取权限信息

next() //当有用户权限的时候,说明所有可访问路由已生成 如访问没权限的全面会自动进入404页面

3.具体代码

router.js

import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)

export const constantRoutes = [
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/login'),
    hidden: true
  },
  {
    path: '/monitor',
    component: () => import('@/views/layout'),
    meta: {
      title: '实时监管',
      icon: ''
    },
    children: [
      {
        path: '/monitor',
        name: 'Monitor',
        component: () => import('@/views/monitor/index')
      }
    ]
  }
]

export const asyncRoutes = [
  {
    path: '/asyncPage',
    component: () => import('@/views/layout'),
    meta: {
      title: '异步加载路由',
      icon: '',
      roles: ['admin']
    },
    children: [
      {
        path: '/asyncPage',
        name: 'AsyncPage',
        component: () => import('@/views/asyncPage/index')
      }
    ]
  },
  {
    path: '*',
    redirect: '/404',
    hidden: true
  }
]

const router = new Router({
  scrollBehavior: () => ({ y: 0 }),
  routes: constantRoutes
})
export default router

vuex

import { asyncRoutes, constantRoutes } from '@/router'

/**
 * Use meta.role to determine if the current user has permission
 * @param roles
 * @param route
 */
function hasPermission(roles, route) {
  if (route.meta && route.meta.roles) {
    return roles.some(role => route.meta.roles.includes(role))
  } else {
    return true
  }
}

/**
 * Filter asynchronous routing tables by recursion
 * @param routes asyncRoutes
 * @param roles
 */
export 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
}

const state = {
  routes: [],
  addRoutes: []
}

const mutations = {
  SET_ROUTES: (state, routes) => {
    state.addRoutes = routes
    state.routes = constantRoutes.concat(routes)
  }
}

const actions = {
  generateRoutes({ commit }, roles) {
    return new Promise(resolve => {
      let accessedRoutes
      if (roles.includes('admin')) {
        accessedRoutes = asyncRoutes || []
      } else {
        accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
      }
      commit('SET_ROUTES', accessedRoutes)
      resolve(accessedRoutes)
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

permission.js

// main.js
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { getToken } from '@/utils/auth' // get token from cookie
import getPageTitle from '@/utils/get-page-title'

NProgress.configure({ showSpinner: false }) // NProgress Configuration

const whiteList = ['/login', '/auth-redirect'] // no redirect whitelist

router.beforeEach(async(to, from, next) => {
  // start progress bar
  NProgress.start()

  // set page title
  document.title = getPageTitle(to.meta.title)

  // determine whether the user has logged in
  const hasToken = getToken()

  if (hasToken) {
    if (to.path === '/login') {
      // if is logged in, redirect to the home page
      next({ path: '/' })
      NProgress.done()
    } else {
      // determine whether the user has obtained his permission roles through getInfo
      const hasRoles = store.getters.roles && store.getters.roles.length > 0
      if (hasRoles) {
        next()
      } else {
        try {
          // get user info
          // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
          const { roles } = await store.dispatch('user/getInfo')
          // generate accessible routes map based on roles
          const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
          // dynamically add accessible routes
          router.addRoutes(accessRoutes)

          // hack method to ensure that addRoutes is complete
          // set the replace: true, so the navigation will not leave a history record
          next({ ...to, replace: true })
        } catch (error) {
          // remove token and go to login page to re-login
          await store.dispatch('user/resetToken')
          Message.error(error || 'Has Error')
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    }
  } else {
    /* has no token*/

    if (whiteList.indexOf(to.path) !== -1) {
      // in the free login whitelist, go directly
      next()
    } else {
      // other pages that do not have permission to access are redirected to the login page.
      next(`/login?redirect=${to.path}`)
      NProgress.done()
    }
  }
})

router.afterEach(() => {
  // finish progress bar
  NProgress.done()
})


  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值