vue element后台鉴权流程分析

前言:

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

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

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

比较:

路由拦截实现方式比较简单,只需要简单的在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)
						//前往拦截的页面
          				next({ ...to, replace: true })
					})
				})
			}
		}
	} else {
		/**这里是处理没有token的情况,也就是说这时候用户还没有登陆,那
		*如果没用户登录,那么判断用户是不是去登录页面,如果是登录
		*页面,就直接放行,如果没登陆就想去访问主页那种页面,就让
		*他重定向到登录页面
		*/
		if(to.path == '/login'){
			//这地方可以判断的仔细一点,不一定是去login的时候再让他直接放行,而是
			//前往所有公共组件的时候,都直接让他放行
			next()
		}else{
			next('/login')
		}
	}
})

 

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 element后台鉴权流程分析的文章就介绍到这了,更多相关vue element鉴权内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • VUE-ElementUI 自定义Loading图操作

    需求: element ui loading图只能使用自己的loading图, 但很多场景下,需要替换成自己的gif图 虽然文档中有些, element-loading-spinner="el-icon-loading" 可指定自定义图 但经测试,也只是只能再elementui 图标库中的图, 不是我们想的那个自定义图类的意思. 自定义图方法: 1) 添加自定义elementUI loading样式 asserts下 新建CSS文件夹 及CSS文件比如myCss.css 再里面,写入自

  • element-plus一个vue3.xUI框架(element-ui的3.x 版初体验)

    突然发现已经半年没更新的element-ui更新了 更新了什么还不清楚,但是告知了基于vue3.x版本的 element-plus 已经出来了. 先来上手体验一下 首先安装一个最新的@vue-cli,搭建一个vue3.x的项目,脚手架创建流程已经很简洁了,这里就不多说了.建好之后,直接开始安装吧 npm i element-plus 为了方便,直接采取全部引入的方式 src/plugins/element.ts import ElementPlus from 'element-plus' imp

  • vue+element_ui上传文件,并传递额外参数操作

    需求: 1.文件大小验证 2.文件类型验证 3.额外参数传输 <template> <el-upload class="upload-demo" action :limit="1" :file-list="formFileList" :http-request="handleUploadForm" :on-exceed="formHandleExceed" :on-remove="

  • 解决vue elementUI 使用el-select 时 change事件的触发问题

    如下所示: <el-select v-model="level" size="mini" placeholder="请选择" :change="selectChange()"> <el-option v-for="item in select" :key="item.value" :label="item.label" :value="it

  • vue element后台鉴权流程分析

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

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

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

  • Vue+Element的后台管理框架的整合实践

    目录 Vue+ElementUI的后台管理框架 那什么是ElementUI? vue-element-admin 是一个后台前端解决方案 路由和配置左侧菜单 新开发的一个后台管理系统.在框架上,领导要用AdminLTE这套模板.这个其实很简单,把该引入的样式和js文件引入就可以了.这里就不多赘述了.可以参考官网:https://adminlte.io/ 效果图,如下: AdminLTE这个模板,还是很方便的.有兴趣的大家可以自行去琢磨.我只是把这个模板内嵌到新系统中去,也就没多去研究了. Adm

  • VUE+element开发后台管理的搜索功能

    本文实例为大家分享了VUE element后台管理搜索功能的具体代码,供大家参考,具体内容如下 先看看样式图: 实现上面这种简单搜索简单的三步走: 1.页面样式:在页面中使用form表单的校验功能来实现输入搜索.给表单的数据放入搜索请求的data数组中,也就是searchParams这个大集合中. 备注:如果给每个输入框添加了搜索按钮的click方法,则会在输入完成后直接执行列表搜索.所以考虑自己使用的具体位置. <div class="search">     <e

  • 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 对外提供服务,

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

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

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

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

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

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

  • vue element table 表格请求后台排序的方法

    1.ElementUi文档已经说了,如果需要后端排序,需将sortable设置为custom,同时在 Table 上监听sort-change事件,在事件回调中可以获取当前排序的字段名和排序顺序,从而向接口请求排序后的表格数据. <el-table :data="playerTableData" border style="width: 100%" :default-sort = "{prop: 'outlay', order: 'descendin

随机推荐