Principles of Routing and Authority Verification

The routing processing logic diagram is as follows:
insert image description here

Routing processing logic diagram analysis:

	// 访问一个路由的时候 --> vue-element-admin框架定义了一个全局的路由守卫,也就是所有要经过路由的都需要访问router.beforeEach,这个方法他具体做了哪些事情
	// 从Cookie中获取Token --> 判断Token是否存在  
		// 第一次访问路由login的时候Token为否 --> 判断路由是否是白名单,如果在白名单就可以直接访问,访问结束 --> 如果访问的路由不在白名单当中,那我们访问的路由 会是 /login?redirecrt=/xxx (后面带一个参数),就是在我们登陆之后会直接重定向到后面这个路由当中
		// 如果有Token我们还访问login --> 会做一个校验路由是否为login --> 他就会重定向到根路径下 
		// 如果有Token 访问补位 login --> 这个时候就会获取角色 --> 生成动态路由 --> 去做权限的校验和匹配 --> 如果匹配到这个路由的时候回通过replace模式来访问这个路由 --> 如果在右侧的过程当中任何一步发生异常,就会进入异常处理逻辑 --> 异常处理逻辑主要有两步,第一步是重置Token,第二步是回到登陆页面

404 (tips)

When none of our above routes match, go back and visit * this route, it will redirect to the 404 page
insert image description here

Routing logic source code

In the first step, the global routing guard is loaded in main.js

import './permission' // permission control

In the second step, permission defines the global routing guard

const whiteList = ['./login','/auth-redirect'] //whiteList 就是白名单 
// 全局路由守卫,所有的路由都将结果这个方法处理 ,最后路由访问一定要调用next,不调是访问不到的
router.beforeEach(async(to, from, next) => {
    
     //debugger模式(条件断点)
  // 启动进度条 显示进度条的功能,首尾呼应
  NProgress.start()

  // 修改页面标题 根据配置项 meta下的title
  document.title = getPageTitle(to.meta.title)

  // 从 Cookie 获取 Token 没有直接undefined 走到else
  const hasToken = getToken()

  // 判断 Token 是否存在
  if (hasToken) {
    
    
    // 如果当前路径为 login 则直接重定向至首页 ,这一步走完会重定向到/本身的重定向
    if (to.path === '/login') {
    
    
      next({
    
     path: '/' })
      NProgress.done()
    } else {
    
    
      // 判断用户的角色是否存在
      const hasRoles = store.getters.roles && store.getters.roles.length > 0
      // 如果用户角色存在,则直接访问
      if (hasRoles) {
    
    
        next()
      } else {
    
    
        try {
    
    
          // 异步获取用户的角色 因为第一次判断没有该角色的存在,所有到这个接口里去找
          const {
    
     roles } = await store.dispatch('user/getInfo')
          // 根据用户角色,动态生成路由
          const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
          // 调用 router.addRoutes 动态添加路由 生成路由表,最后会根据路由表生成左侧的菜单栏
          router.addRoutes(accessRoutes)
          // 使用 replace 访问路由,不会在 history 中留下记录 会回退到一个空页面
          next({
    
     ...to, replace: true })
        } catch (error) {
    
    
          // 移除 Token 数据
          await store.dispatch('user/resetToken')
          // 显示错误提示
          Message.error(error || 'Has Error')
          // 重定向至登录页面
          next(`/login?redirect=${
      
      to.path}`)
          NProgress.done()
        }
      }
    }
  } else {
    
    
    // 如果访问的 URL 在白名单中,则直接访问  to就是你要到哪里去 (就是查看whiteList中是否包含你要访问的地址)
    if (whiteList.indexOf(to.path) !== -1) {
    
    
    // 当他不等于-1 这个时候就会直接访问
      next()
    } else {
    
    
      // 如果访问的 URL 不在白名单中,则直接重定向到登录页面,并将访问的 URL 添加到 redirect 参数中
      next(`/login?redirect=${
      
      to.path}`)
      NProgress.done()
    }
  }
})
// 路由访问成功之后 访问afterEach
router.afterEach(() => {
    
    
  // 停止进度条
  NProgress.done()
})

Dynamic Routing Analysis

Dynamic Routing Flowchart

The dynamic route generation logic is as follows:
insert image description here

Analysis of dynamic routing graph

// 将constantRoutes和asyncRoutes都读取出来 --> 获取用户的角色 roles --> 判断roles是否为admin
	// 是admin的话会直接将asyncRoutes保存到vuex当中 --> 将asyncRoutes 与 constantRoutes合并 (就是说你有admin权限会跳过所有的判断)
	// 如果不是admin --> 会遍历所有的角色,取出所有的角色 --> 判断是否具有访问路由权限 
		// 没有访问路由权限,我们会遍历下一个
		// 有访问权限会判断路由当中是否存在子路由	
			// 如果有子路由,我们会用迭代在去遍历子路由,子路由中会进行过滤后会将我们现在这个children进行更新,将不符合条件的子路由全部去除掉
			// 最后当判断完成后,把路由存到一个新的数组当中,把这个数组替换原来的asyncRoutes,保存到vuex当中,最后将asyncRoutes和constantRoutes进行合并

Dynamic routing source code analysis

The source code for generating dynamic routes is located in the generateRoutes method in src/store/modules/permission.js. The source code is as follows:

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

generateRoutes({
     
      commit }, roles) {
    
    
  // 返回 Promise 对象
  return new Promise(resolve => {
    
    
    let accessedRoutes
    //判断roles当中是否包含admin
    if (roles.includes('admin')) {
    
    
      // 如果角色中包含 admin,则直接跳过判断,直接将 asyncRoutes 全部返回
      accessedRoutes = asyncRoutes || []
    } else {
    
    
      // 如果角色中没有包含 admin,则调用 filterAsyncRoutes 过滤路由
      accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
    }
    // 将路由保存到 vuex 中
    commit('SET_ROUTES', accessedRoutes)
    resolve(accessedRoutes)
  })
}

The source code of the SET_ROUTES method is as follows:

SET_ROUTES: (state, routes) => {
    
    
  // 将 routes 保存到 state 中的 addRoutes
  state.addRoutes = routes
  // 将 routes 集成到 src/router/index.js 的 constantRoutes 中
  state.routes = constantRoutes.concat(routes)
}

The source code of the route filtering method filterAsyncRoutes is as follows:

/**
 * @params routes - 异步加载的路由
 * @params roles - 用户的角色,数组形式
 */
export function filterAsyncRoutes(routes, roles) {
    
    
  const res = []

  // 遍历全部路由
  routes.forEach(route => {
    
    
    // 对路由进行浅拷贝,注意 children 不会拷贝,因为不需要对 children 进行判断,所以可以使用浅拷贝
    const tmp = {
    
     ...route }
    // 检查用户角色是否具备访问路由的权限
    if (hasPermission(roles, tmp)) {
    
    
      // 当路由具有访问权限时,判断路由是否具备 children 属性
      if (tmp.children) {
    
    
        // 当路由包含 children 时,对 children 迭代调用 filterAsyncRoutes 方法
        tmp.children = filterAsyncRoutes(tmp.children, roles)
      }
      // 当路由具有访问权限时,将 tmp 保存到 res 中
      res.push(tmp)
    }
  })

  return res
}

The source code of the method hasPermission for checking permissions is as follows:

function hasPermission(roles, route) {
    
    
  // 检查路由是否包含 meta 和 meta.roles 属性
  if (route.meta && route.meta.roles) {
    
    
    // 判断 route.meta.roles 中是否包含用户角色 roles 中的任何一个权限,如果包含则返回 true,否则为 false
    return roles.some(role => route.meta.roles.includes(role))
  } else {
    
    
    // 如果路由没有 meta 或 meta.roles 属性,则视为该路由不需要进行权限控制,所有用户对该路由都具有访问权限
    return true
  }
}

Relevant library analysis

NProgress

Slim progress bars for Ajax’y applications. Inspired by Google, YouTube, and Medium.

NProgress.start();
NProgress.done();

showSpinner can control whether the circular progress bar on the right is displayed

NProgress.configure({
    
     showSpinner: false })

Summarize

About routing processing
  • vue-element-admin intercepts all accessed routes;
  • When accessing the route, the Token will be obtained from the cookie to determine whether the Token exists :
    + If the Token exists, a dynamic route will be generated according to the user role, and then the route will be accessed to generate the corresponding page component. There is a special case here, that is, when the user accesses /login, it will be redirected to the / route;
    + If the Token does not exist, it will be judged whether the route is in the whitelist, if it is in the whitelist, it will be directly accessed, otherwise it means that the route needs to be logged in to Access, at this time, a redirect parameter generated by the route will be passed to the login component, and the actual accessed route is: /login?redirect=/xxx.
  • About dynamic routing and permission verification
    + vue-element-admin divides routing into: constantRoutes and asyncRoutes
    + When users log in to the system, routes will be dynamically generated, of which constantRoutes must be included, and asyncRoutes will filter;
    + The logic of asyncRoutes filtering is to look at routing Does it contain the meta and meta.roles attributes? If not, this is a general route and does not require permission verification; if it contains the roles attribute, it will determine whether the user's role hits any permission in the route. If it hits , the route will be saved, and if it is not hit, the route will be discarded directly;
    + After asyncRoutes is processed, it will be merged with constantRoutes into a new route object and saved in the permission/routes of vuex;
    + After the user logs in to the system , the sidebar will get state.permission.routes from vuex, and dynamically render the user menu according to the route.

vue admin
login process
interface simplification and routing processing (permission control is realized)
routing and permission verification principle
sidebar
redirection
breadcrumb navigation
requst library axios interception
login component implementation details

Guess you like

Origin blog.csdn.net/qq_52151772/article/details/111242844
Recommended