vue-router后台鉴权流程实现

目录
  • 前言:
  • 路由拦截鉴权常用的两种方法
  • 比较:
  • 与动态路由相关的通常有以下几个文件:
  • router.js
  • permission.js
  • store.js
  • 退出登录:
  • 结尾:

前言:

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

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

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

比较:

路由拦截实现方式比较简单,只需要简单的在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"){
            /**
            *用户已经登陆,但是还路由到login页面,这代表用户已经执行了退出登录的操
            *作,所以这个地方可以清一下token之类的,或者自定义写一些逻辑
            */
            next()
        }else{
        /**
        *这里是已经登录或者点击了登录按钮,token已经存入localstorage,但是但是不路
        *由到login的情况如果没有路由到/login,那么就直接让他放行就行,在这里面我处
        *理一些东西,就是用户既然已经登陆,并且可以直接放行,那么我们放
        *行之前,在这个地方需要做一些逻辑,就是判断用户的权限,然后根
        *据用户的权限,把我们的动态配置的路由表中符合他权限的那几条路
        *由给过滤出来,然后插入到路由配置表中去使用
        *
        *那么就涉及到两个问题:
        *1:什么时候去处理动态路由(登陆之后,进入到首页之前,也就
        *是next之前)
        *2:什么条件处理动态路由
        */
        
        /**
        *这地方可以先判断一下store中的用户权限列表长度是否为0,若长度为0,则代表用户
        *是刚点击了登录按钮,但是还没有进入到页面,这时候需要再去做一些权限过滤之类的    
        *操作如果长度不为0代表鉴权流程都没问题了,直接前往对应的组件就行
        *这一步主要是为了防止重复过滤数组,节约性能
        */
            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 {
        /**这里是处理没有token的情况,也就是说这时候用户还没有登陆,那
        *如果没用户登录,那么判断用户是不是去登录页面,如果是登录
        *页面,就直接放行,如果没登陆就想去访问主页那种页面,就让
        *他重定向到登录页面
        */
        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 = {
    /**把state中的roles存入到这个getters中,那么其他获取这个getters中的
    *roles的地方,只要原本的roles发生改变,其他地方的这个roles也就会发生
    *改变了,这个相当于是computed计算属性
    */
    roles:state => state.roles
    allRouters:state => state.allRouters
    addRouters:state => state.addRouters
}
const mutations:{
    /**在下面的actions里面通过commit把权限信息的数组提交到这个地方,然后
    *这个地方把数组提交到state的roles
    */
    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后台鉴权 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue-router中关于children的使用方法

    目录 关于children的使用 children的使用场景 router配置中children配置不起作用 关于children的使用 children的使用场景 比如页面左侧显示菜单,右侧显示不同菜单下的内容,类似如下element网站,那么右侧部分的内容就是当前页面的children 存在如下场景,点击导航一跳转至页面1,导航二跳转页面2,且页面1中存在子页面 路由js如下: const routes = [{ path: '/', name: 'Home', component: Hom

  • Vue--Router动态路由的用法示例详解

    目录 官网网址 动态路由概述 同一路由多个参数 path-to-regexp Api用法 1. pathToRegexp() 2.exec() 3. parse() 4. compile() 本文介绍Vue-Router中动态路由的用法. 官网网址 Vue官网:带参数的动态路由匹配 | Vue Router 动态路由概述 说明 很多时候,我们需要将给定匹配模式的路由映射到同一个组件.例如,我们可能有一个 User 组件,它应该对所有用户进行渲染,但用户 ID 不同.在 Vue Router 中,

  • Vue Router深扒实现原理

    目录 回顾Vue Router的核心代码 代码实现 创建Vue-Router插件 构造函数 完整代码 Vue Router官网 前置知识:插件.slot插槽.mixins混入.render函数.运行时和完整版的Vue 回顾Vue Router的核心代码 // 注册插件 // Vue.use() 内部调用传入对象的 install 方法 Vue.use(VueRouter) // 创建路由对象 const router = new VueRouter({ routes: [ { name: 'ho

  • 关于VueRouter导入的全过程

    目录 router nanoid的使用 引入 使用 路由 1-1 安装依赖 1-2 引入 1-3 在main.js中使用 1-4 App.vue 全局过滤器 element-ui 全局组件 Vuc-cli中的视配 1-1 安装依赖 1-2 配置文件 1-3 main.js 1-4 public/index.html 1-5 在pc端视配 slot封装动画 项目初始化 1-1 .router-link-active 1-2 动态显示tabbar 1-3 跳转回前一个页面 1-4轮播 vant ui

  • Vue Router路由hash模式与history模式详细介绍

    目录 一.前言 二.hash模式 三.history模式 一.前言 对于hash模式和history模式,最直接的区别就是地址栏带不带"#"号了. vue脚手架搭建的项目的路由默认是hash模式. hash模式: 创建路由实例时,添加mode:"history"属性,即可使用history模式. const router = new VueRouter({ routes, mode: "history" }) history模式: 二.hash模

  • Vue Router解决多路由复用同一组件页面不刷新问题(场景分析)

    目录 简介 问题复现 代码 测试 解决方案 方案1:导航守卫 方案2:watch监听$route 方案3:父组件router-view指定key 其他网址 简介 说明 本文介绍如何解决Vue的多路由复用同一组件页面不刷新问题. 多路由复用同一组件的场景 多路由使用同一组件 比如:添加博客(path为:/addBlog)和编辑博客(path为:/editBlog)都对应同一个组件(EditBlog.vue) 动态路由 比如:用户详情页采用动态路由,其path为:/user/:id,组件都是User

  • vue element后台鉴权流程分析

    前言: 最近项目遇到一个管理系统,感觉权限配置挺有意思,记录一下流程实现的过程,便于自己学习以及整理思路,部分思路整合在代码的注释中: 路由拦截鉴权常用的两种方法 1:路由拦截:单纯给路由加字段标识符,通过路由拦截实现 2:动态路由:第二种是通过路由的拆分另外需要后端的配合去实现的动态路由配置 比较: 路由拦截实现方式比较简单,只需要简单的在router.beforeEach中根据路由配置信息过滤页面是否有权限前往改组件,若相对于的权限不够则不前往相应的组件 动态路由实现相对比较复杂,并且需要后

  • vue-router后台鉴权流程实现

    目录 前言: 路由拦截鉴权常用的两种方法 比较: 与动态路由相关的通常有以下几个文件: router.js permission.js store.js 退出登录: 结尾: 前言: 最近项目遇到一个管理系统,感觉权限配置挺有意思,记录一下流程实现的过程,便于自己学习以及整理思路,部分思路整合在代码的注释中: 路由拦截鉴权常用的两种方法 路由拦截:单纯给路由加字段标识符,通过路由拦截实现动态路由:第二种是通过路由的拆分另外需要后端的配合去实现的动态路由配置 比较: 路由拦截实现方式比较简单,只需要

  • Vue Router根据后台数据加载不同的组件实现

    目录 实际项目中遇到的需求 有一些不好的实现方式 个人感觉比较好的实现方式 功能已实现,但我又开始了新的思考 最终方案--高阶组件 实际项目中遇到的需求 同一个链接需要加载不同的页面组件.根据用户所购买服务的不同,有不同的页面展现. 有一些不好的实现方式 直接把这几个组件写在同一个组件下,通过v-if去判断.如果这么做的话,甚至可以不使用vue-router,直接把所有组件,都写在一个文件里面,全部通过v-if判断,也是可行的.(前提是几万行代码一起,你不嫌麻烦的话) 在渲染这个链接的时候,直接

  • React路由鉴权的实现方法

    前言 上一篇文章中有同学提到路由鉴权,由于时间关系没有写,本文将针对这一特性对 vue 和 react 做专门说明,希望同学看了以后能够受益匪浅,对你的项目能够有所帮助,本文借鉴了很多大佬的文章篇幅也是比较长的. 背景 单独项目中是希望根据登录人来看下这个人是不是有权限进入当前页面.虽然服务端做了进行接口的权限,但是每一个路由加载的时候都要去请求这个接口太浪费了.有时候是通过SESSIONID来校验登陆权限的. 在正式开始 react 路由鉴权之前我们先看一下vue的路由鉴权是如何工作的: 一.

  • Kubernetes 权限管理认证鉴权详解

    目录 正文 认证 认证用户 Normal Users Service Accounts 认证策略 客户端证书 不记名令牌 Static Token File Service Account Tokens OpenID Connect Tokens 鉴权 鉴权流程 鉴权模块 RBAC Role 和 ClusterRole RoleBinding 和 ClusterRoleBinding Service Account 最后 正文 Kubernetes 主要通过 API Server 对外提供服务,

  • 详解如何使用Vuex实现Vue后台管理中的角色鉴权

    目录 前言 功能分析 实现思路 代码实现 vuex中定义user模块,存储用户信息以及用户侧边导航数据 router中路由meta中新增roles 定义当前路由可以访问的所有的角色 router新增路由前置首位 做权限拦截 侧边导航页面 使用 getters中的 authMenus 循环侧边导航 最后一步 登录页登录时调用 请求登录的action即可大功告成 总结 前言 一直以来,我们使用vue做后台管理时,不同角色的权限功能,都是我们老大难的问题,本篇文章我将手把你带你实现vue后台管理中的用

  • koa2服务端使用jwt进行鉴权及路由权限分发的流程分析

    大体思路 后端书写REST api时,有一些api是非常敏感的,比如获取用户个人信息,查看所有用户列表,修改密码等.如果不对这些api进行保护,那么别人就可以很容易地获取并调用这些 api 进行操作. 所以对于一些api,在调用之前,我们在服务端必须先对操作者进行"身份认证",这就是所谓的鉴权. Json Web Token 简称为 JWT,它定义了一种通信双方之间以 JSON 对象的形式安全传递信息的方法.JWT 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名,复杂度较

  • Vue中axios的封装(报错、鉴权、跳转、拦截、提示)

    统一捕获接口报错 弹窗提示 报错重定向 基础鉴权 表单序列化 实现的功能 统一捕获接口报错 : 用的axios内置的拦截器 弹窗提示: 引入 Element UI 的 Message 组件 报错重定向: 路由钩子 基础鉴权: 服务端过期时间戳和token,还有借助路由的钩子 表单序列化: 我这边直接用 qs (npm模块),你有时间也可以自己写 用法及封装 用法 // 服务层 , import默认会找该目录下index.js的文件,这个可能有小伙伴不知道 // 可以去了解npm的引入和es6引入

  • nuxt框架中路由鉴权之Koa和Session的用法

    引子 博客的后台管理页面需要有登录系统,所以考虑做一下路由鉴权,实现方式也是 Nuxt 官网给出栗子来改写,顺便也将前后端路由给统一了. 路由拦截 前端方面主要通过利用 Nuxt 的中间件来做路由拦截,这里也是需要 Vuex 状态树来做. middleware middleware/auth.js export default function ({ store, redirect }) { if (!store.state.user) { return redirect('/login') }

  • 聊聊鉴权那些事(推荐)

    在系统级项目开发时常常会遇到一个问题就是鉴权,身为一个前端来说可能我们距离鉴权可能比较远,一般来说我们也只是去应用,并没有对权限这一部分进行深入的理解. 什么是鉴权 鉴权:是指验证用户是否拥有访问系统的权利.传统的鉴权是通过密码来验证的.这种方式的前提是,每个获得密码的用户都已经被授权.在建立用户时,就为此用户分配一个密码,用户的密码可以由管理员指定,也可以由用户自行申请.这种方式的弱点十分明显:一旦密码被偷或用户遗失密码,情况就会十分麻烦,需要管理员对用户密码进行重新修改,而修改密码之前还要人

随机推荐