我的编程空间,编程开发者的网络收藏夹
学习永远不晚

vue-router后台鉴权流程实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

vue-router后台鉴权流程实现

前言:

最近项目遇到一个管理系统,感觉权限配置挺有意思,记录一下流程实现的过程,便于自己学习以及整理思路,部分思路整合在代码的注释中:

路由拦截鉴权常用的两种方法

路由拦截:单纯给路由加字段标识符,通过路由拦截实现
动态路由:第二种是通过路由的拆分另外需要后端的配合去实现的动态路由配置

比较:

路由拦截实现方式比较简单,只需要简单的在router.beforeEach中根据路由配置信息过滤页面是否有权限前往改组件,若相对于的权限不够则不前往相应的组件
动态路由实现相对比较复杂,并且需要后端的配合,本质是路由配置表分成两部分,相应的不同用户登录的时候,是根据用户权限信息过滤筛选除路由配置表,动态添加,而用户没有权限的部分则不渲染,更适合相对比较大型的后台系统

注:本篇内容主要介绍动态路由鉴权实现方式

与动态路由相关的通常有以下几个文件:

  • router.js
  • permission.js(全局的路由拦截文件)
  • store.js

router.js

router.js的路由配置表可以分为两部分,公共路由以及动态权限路由,动态权限路由可以放在前端,鉴权的时候前端自己进行数组的过滤,也可以放在后端过滤,思路相同,下面介绍的是配置表都放在前端的

export default new  Router({ 
routes:[
   {
        path:'/login',
        name:'login',
        component:aa
    },
    {
        path:'/home',
        name:'home',
        component:cc
    },
    ]
})

上面这个是一般项目的路由配置,现在我们需要做鉴权所以需要把路由配置表稍微拆分一下,拆成以下两个数组:

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

export const defauleRoute = [ //固定部分权限的数组,所有用户都能访问的路由
    {
        path:'/login',
        component:aa
    },
]

export const  asyncRoute = [ //动态配置的路由表,工作之前需要过滤
    {
        path:'/order',
        name:'order',
        component:aa,
        meta:{
            system:'order'
        }
    }
    {
        path:'/roles',
        name:'roles',
        component:aa,
        meta:{
            system:'roles'
        }
    }
]

//注册路由工作表
const createRouter = () => new Router({
      // mode: 'history', // require service support
      scrollBehavior: () => ({ y: 0 }),
      routes: constantRoutes
})
const router = createRouter()

//重置路由工作表,退出登录的时候需要调用此方法
export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher 
}

export default router

permission.js

permission文件主要做全局的路由拦截,以及路由根据用户权限动态过滤等功能,那么这部分内容主要设涉及的就是两个问题

  • 什么时候去处理动态路由
  • 什么条件去处理路由
import router from './router'
import store from './store'
import { getToken } from '@/utils/auth' // 自定义封装存取token的方法

Route.beforeEach((to,from,next) =>{
    //取token,判断用户是否已登录
    const  hasToken = getToken() 
    if(hasToken ){
    //判断用户已登录
        if(to.path === "/login"){
            
            next()
        }else{
        
        
        
            if(store.getters.roles.length > 0){
                next()
            }else{
                //代码如果走到了这个地方,代表用户是已登录。并且鉴权流程还没走,
                //那么在这地方就需要去走鉴权流程
                store.dispatch('getRoles').then(res=>{
                    //这个地方的res是第三步那个地方的peomise中的resolve传
                    //过来的,也就是权限信息的那个数组
                    store.dispatch('createRouters',res.data)
                    .then(res=>{
                        //这里是调用store创造动态路由的那个函数,这个地方可以把那
                        //个权限数组传到这个函数内部,或者不在这里传,这个
                        //函数内部直接去取自己state里面的roles的值也是一样的
                        let  addRouters = store.getters('addRouters')
                        let  allRouters = store.getters('allRouters')

                        //添加动态路由部分到工作路由
                        router.addRoutes(accessRoutes)
                        //vue/cli4及之后的版本,addRoutes被废弃,取而代之的是
                        //addRoute('paramentsName',route对象)或者            
                        //addRoute(route对象),注意,传进去的参数不再是一个数组,
                        //而是每一条路由对象,如果套添加多条,那么就需要遍历添加
                        //如果是传两个参数的写法,那么第一个参数是父路由的名字
                        //这样就是把这条路由加入到父路由的children里面去        

                        //前往拦截的页面
                          next({ ...to, replace: true })
                          //addRoute添加完路由之后一定要通过这种方式做路由跳转,
                          //不然可能会导致addRoute之后的第一次跳到addRoutes添加的页
                          //面的时候,可能是空白页面
                          
                          //{...to}:作用:把整个路由对象传过去做路由跳转,包括带上
                          //components那些,这样就能保证第一次就能渲染到这个页面
                          //replace:true:本次路由记录不被浏览器所记录
                    })    
                })
            }
        }
    } else {
        
        if(to.path == '/login'){
            //这地方可以判断的仔细一点,不一定是去login的时候再让他直接放行,而是
            //前往所有公共组件的时候,都直接让他放行
            next()
        }else{
            next('/login')
        }
    }
})

addRoutes动态添加路由两个注意点:

addRoutes:
Vue/cli4及之后的版本,addRoutes被废弃,取而代之是addRoute('parentName',Route)或者addRoute(route对象),如果是传两个参数的写法,那么第一个参数是父路由的name这样就是把这条路由加入到父路由的children里面去,如果是要动态添加多天路由,就需要通过遍历的方式了next({ ...to, replace: true }):
addRoute首次添加完路由之后的路由跳转一定要通过这种方式做路由跳转,不然可能会导致addRoute之后的第一次跳到addRoutes添加的页面的时候,可能是空白页面

{...to}:作用:把整个路由对象传过去做路由跳转,包括带上components那些,这样就能保证第一次前往addRoutes动态添加的就能渲染到这个页面
replace:true:本次路由记录不被浏览器所记录

store.js

//在api文件夹中定义一个获取此用户的权限的接口,并且在这个actions中调用
import { getUserRole } from "../api/getRoles"  //获取权限的接口
import { logout } from '../api/user'   //用户退出登录的接口
import { resetRouter } from './router'
import { removeToken } from '@/utils/auth' // 自定义封装清除token的方法

//这个是过滤数组的方法,如果路由表是多层嵌套的,那么可以递归调用这个方法去过滤数组
//function hasPermission(roles, route) {
//  if (route.meta && route.meta.roles) {
//    return roles.some(role => route.meta.roles.includes(role))
//  } else {
//    return true
//  }
//}

//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
//}

//引入默认路由以及动态路由
import  { defauleRoute , asyncRouter }  from '@/router'
const state = {
    roles:[]    //掉接口拿到的权限列表,假设数据格式为:["order","roles"],
    allRouters: [], //这个是全部整合以后,最终要工作的路由
    addRouters: [],//这个是根据权限动态匹配过滤出来部分的路由
}
      
const getters = {
    
    roles:state => state.roles
    allRouters:state => state.allRouters
    addRouters:state => state.addRouters
}
const mutations:{
    
    SetRoute(state,router)
        //这个地方的router就是根据用户权限,过滤出来的路由表
        state.allRouters = defauleRoute.concat(router)
        state.addRouters = router
    }
    //把路由权限数组存储到state
    setRoles(state,value){
        state.roles = value
    }
}
const actions:{
    //写一个获取当前登陆角色权限的请求,比如["/order","roles"],如果请求回
    //来的是这样的,那么就代表这个角色的权限就是可以访问 order路由以及
    //roles路由
    
    //获取权限信息可能有两种情况:除了下面这种权限信息是一个单独的接口,
    //权限信息也可能跟着用户登陆的接口就一并返回
    //获取当前用户的权限信息,并且存入到state中,这个权限信息,可能跟后
    //端在沟通的时候,他不会单独写成一个接口给你去请求,而是你在登陆请求
    //的时候就把用户信息和这个此用户的权限信息都一次性返回给你了,那就在
    //用户登陆的时候就把这个权限信息存入到这个state中,也一
    //样的,目的就是要把权限信息的数组存入到state中就行
    //获取roles权限方法
    getRoles({commit},data){
        return new Promise(resolve,reject){
            //调用获取用户权限接口
            getUserRole().then(res =>{
                //这里返回的数据应该是一个权限信息的数组,如:["order","roles"]
                //把权限信息通过mutations存入到state
                commit('setRoles',res.data)
                resolve(res.data)
            })
        }
    })
    //根据权限过滤数组配置表的方法
    createRouters({ commit } , data ){
        return new Promise((resolve,reject) =>{
            let addRouters =  [ ] 
            if(data.includes("admin"){
                addRouters = asyncRouter
            }else{
                //项目开发中路由数组可能是多层嵌套,那么这地方需要用上面自定义的方    
                //法通过递归的方式去过滤,此demo就只按一层数组处理
                //(filterAsyncRoutes)方法
                addRouters = asyncRouter.filter(item=>{
                    if(data.includes(item.meta.system) ){
                           return item
                    }
                })
            }
            
            
            //把这个匹配出来的权限路由传到mutations中,让mutations
            //把这个匹配出来的路由存入到state
            commit.("SetRoute",addRouters)
            resolve()  //这个地方要调用一下这个resolve,这样外面访可以通过
                       //.then拿到数组过滤成功的回调
        })
    },
    logout({ commit }) {
        return new Promise((resolve, reject) => {
          logout().then(() => {
            removeToken() // must remove  token  first
            resetRouter()
            commit('setRoles', [])
            commit('SetRoute', [])
            resolve()
          }).catch(error => {
            reject(error)
          })
        })
  },
}
export default {
    state,
    getters,
    mutations,
    actions
}

退出登录:

async function logout(){
    try{
        const res = await store.dispatch.logout()
        if(res.code == 200){
            //退出登录成功
        }
    }catch{
        //退出登录失败(出错了)
    }
}

结尾:

代码一大堆,其实思路很简单,不过是拿到路由配置表,过滤数组,动态添加而已

项目参考github:vue-element-admin

到此这篇关于vue-router后台鉴权流程实现的文章就介绍到这了,更多相关vue-router后台鉴权 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

vue-router后台鉴权流程实现

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

vue-router后台鉴权流程实现

本文主要介绍了vue-router后台鉴权流程实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2022-11-13

怎么使用Vuex实现Vue后台管理中的角色鉴权

这篇文章主要介绍“怎么使用Vuex实现Vue后台管理中的角色鉴权”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么使用Vuex实现Vue后台管理中的角色鉴权”文章能帮助大家解决问题。功能分析在常见管
2023-06-30

AndroidWorkManager实现后台定时任务流程详解

WorkManager是AndroidJetpack的一个强大的组件,用于处理后台耗时任务。后台任务可以是一次性的,也可以是重复的,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
2023-01-30

Vue生命周期与后端交互实现流程详解

Vue的生命周期就是vue实例从创建到销毁的全过程,也就是newVue()开始就是vue生命周期的开始。Vue实例有⼀个完整的⽣命周期,也就是从开始创建、初始化数据、编译模版、挂载Dom->渲染、更新->渲染、卸载等⼀系列过程,称这是Vue的⽣命周期
2022-11-13

编程热搜

目录