美文网首页
vue-element-admin登录流程

vue-element-admin登录流程

作者: Mracale | 来源:发表于2021-10-29 16:39 被阅读0次

    项目模板采用vue-element-admin,使用vue和element-ui实现

    1.目录结构


    image.png

    permission.js
    登录流程中,src/permission.js是最重要的环节,这个文件是路由的全局钩子(beforeEach和afterEach),全局钩子的意思就是每次跳转的时候可以根据情况进行拦截,不让他跳转。使用场景就是有些页面需要登录才能访问,这时候就可以在beforeEach中校验用户登录状态来进行拦截。

    utils/auth.js
    设置token到cookie中的操作封装。

    router
    有关路由的一些设置

    二、登录流程解析

    登录页面:view/login/index.vue


    image.png

    点击登录按钮后,触发handleLogin方法,利用validate进行表单验证,如果验证通过,调用user/login方法传递表单里的数据,根据.then回调执行this.$router.push方法,这个方法用于跟踪:我是从哪里跳到/login页面的,登录后我就返回哪里。

    /user/login方法:src/store/modules/user.js

    image.png

    这个方法主要做了以下工作:登录验证,登录成功后,分别把token保存在vuex和cookie中。

    permission.js :src/permission.js

    router.beforeEach(async(to, from, next) => {
      // 从cookie中取得token
      const hasToken = getToken()
      
      // 如果有token 也就是已经登陆的情况下
      if (hasToken) {
        // 并且要前往的路径是'/login'  则返回 '/' 
        if (to.path === '/login') {
          next({ path: '/' })
        } else {
          // 从store中取得用户的 roles, 也就是用户的权限 并且用户的权限数组必须有一个以上
          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(accessRoutes)
              // 进入路由
              next({ ...to, replace: true })
            } catch (error) {
              // 如果出现异常  清空路由 
              await store.dispatch('user/resetToken')
              // Message提示错误
              Message.error(error || 'Has Error')
              // 跳到login页面重新登陆
              next(`/login?redirect=${to.path}`)
            }
          }
        }
      } else {
        // 没有token 也就是没有登陆的情况下  
        // 判断是否是白名单(也就是说不需要登陆就可以访问的路由)
        if (whiteList.indexOf(to.path) !== -1) {
          next()
        } else {
          // 其他的一律给我跳到login页面 老老实实的进行登陆
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    })
    
    
    

    利用beforeEach进行访问拦截,如果没登录,跳转到登录页面进行登录。

    user/getInfo:src/store/modules/user.js


    image.png

    getInfo用于获取用户信息并保存到vuex中,后面是一堆的数据校验。

    permission/generateRoutes:src/store/modules/permission.js

    // 判断是否有权限
    function hasPermission(roles, route) {
      if (route.meta && route.meta.roles) {
        // roles.some => Array.some 相当于是只要有一个满足就为true 
          
        // 判断用户的权限于当前路由访问所需要的权限是否有一个满足
        // 比如说用户权限为 ['one','two']  当前路由访问所需要权限为 ['two','three']  那么就说明当前用户可以访问这个路由
        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
    }
    // 为什么要写这里呢,因为后面的Sidebar组件与这个环环相扣
    const mutations = {
      SET_ROUTES: (state, routes) => {
        // 添加的路由
        state.addRoutes = routes
        // 将vuex中的路由进行更新
        state.routes = constantRoutes.concat(routes)
      }
    }
    const actions = {
      generateRoutes({ commit }, roles) {
        return new Promise(resolve => {
          let accessedRoutes
          // 如果roles包含 'admin' 直接可以全部访问
          if (roles.includes('admin')) {
            accessedRoutes = asyncRoutes || []
          } else {
            // 利用 filterAsyncRoutes 过滤出可访问的路由
            accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
          }
          // 保存可访问的路由到store中
          commit('SET_ROUTES', accessedRoutes)
          // 将可访问路由返回
          resolve(accessedRoutes)
        })
      }
    }
    
    

    generateRoutes就是根据得到的用户权限生成可以访问的路由。

    动态路由实现
    router.addRoutes(accessRoutes)

    动态路由的核心代码就这一句话,短小精悍,其他的都是为了完成动态路由做的一些 “准备工作” ,user/getInfo获取用户信息得到用户的roles权限数组,返回user/generateRoutes生成可访问路由,就是这么神奇的一步,实现了动态路由。

    三、总结
    1 Login/index.vue点击登陆 提交user/login的actions。
    2 user/login进行登陆验证,登陆成功之后保存token到vuex和cookie中。
    3 回到Login/index.vue跳转路由,这时就到了permission.js
    4 permission.js进行判断是否登陆,是否有用户信息?没有用户信息就获取用户信息,并且保存到vuex,然后根据用户信息中的roles生成可访问路由,并通过addRoutes进行添加。

    登录流程图

    image.png

    相关文章

      网友评论

          本文标题:vue-element-admin登录流程

          本文链接:https://www.haomeiwen.com/subject/cggialtx.html