vue element后台鉴权流程分析
编程学习 2021-07-04 14:07www.dzhlxh.cn编程入门
这篇文章主要介绍了vue element后台鉴权流程分析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
前言:
最近项目遇到一个管理系统,感觉权限配置挺有意思,记录一下流程实现的过程,便于自己学习以及整理思路,部分思路整合在代码的注释中:
路由拦截鉴权常用的两种方法
1:路由拦截:单纯给路由加字段标识符,通过路由拦截实现
2:动态路由:第二种是通过路由的拆分另外需要后端的配合去实现的动态路由配置
比较:
路由拦截实现方式比较简单,只需要简单的在router.beforeEach中根据路由配置信息过滤页面是否有权限前往改组件,若相对于的权限不够则不前往相应的组件
动态路由实现相对比较复杂,并且需要后端的配合,本质是路由配置表分成两部分,相应的不同用户登录的时候,是根据用户权限信息过滤筛选除路由配置表,动态添加,而用户没有权限的部分则不渲染,更适合相对比较大型的后台系统
注:本篇内容主要介绍动态路由鉴权实现方式
与动态路由相关的通常有以下几个文件:
- router.js
- permission.js(全局的路由拦截文件)
- store.js
router.js
router.js的路由配置表可以分为两部分,公共路由以及动态权限路由,动态权限路由可以放在前端,鉴权的时候前端自己进行数组的过滤,也可以放在后端过滤,思路相同,狼蚁网站SEO优化介绍的是配置表都放在前端的
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 // } /