Vue单点登录与特殊路由跳转开发初体验!

858 阅读2分钟

接到需求

某一天,项目leader走过来跟我说,我们要实现B系统单点登录跳转A系统的功能,具体如下:

从B系统通过携带cas信息跳转A系统时,如验证凭证有效则无需账号密码手动登录,直接进入A系统。

另外还附带了两个路由跳转需求:

1.点击页面链接,若因为没有权限跳转登录页,登录成功后再跳回该页面。

2.若url中有redirect指定页面,则登录成功后跳到redirect的页面。

项目leader发话了,我立马领会精神开干了。

开发分析

A系统是一个Vue2 web项目,已经运行两年了,其已经有一套登录路由跳转逻辑了,这次新增加的功能,只需要在原有代码上进行改造就行了。

代码分析

项目中,涉及到登录路由跳转的,关键在于两个文件

1.login/index.vue

2.permission.js

通过代码分析发现,针对leader提出的路由跳转需求2,代码已经局部实现了,但是场景覆盖不全,而单点登录和路由跳转需求1,则需要重新实现。

具体实现

1.login/index.vue中,监听路由,根据路由参数进行处理

  • 登录

    若路由参数中有cas参数,则去进行接口验证,验证通过后,即可自动登录进入系统,实现单点登录。

    若路由参数中无cas参数,或接口验证不成功,则停留在登录页,由用户手动登录。

  • 登录成功跳转的页面

    若参数中有redirect指定跳转页面,则登录成功后直接跳转到redirect页面。

    如参数中没有redirect,则跳转至菜单列表中的第一个。

<template></template>
<script>
    export default {
       data() {
           return {
                redirect: undefined,
                otherQuery: {},
           }
       }
       watch: {
           $route: {
               handler: function (route) {
                   const query = route.query;
                   if (query)
                       if(query.redirect) {
                           this.redirect = query.redirect
                       }
                       this.otherQuery = this.getOtherQuery(query);
                       // 当路由参数中有cas时,去验证cas并自动登录
                       if(query.cas) {
                         this.autoLogin(query.cas)
                       }
                   }
                },
                immediate: true,
             },
        },
        methods: {
            // cas免登陆
            autoLogin(cas) {
               this.$store.dispatch("user/casLogin", cas).then(() => {
                  // 登录成功后,跳转菜单
                  this.goMemu()
               }).catch((err) => {
               });
            },
            // 规定路由跳转逻辑
            goMemu() {
               const restlist = this.$store.getters && store.getters.permission_routes || []
               let path = ''
               const defPath = findFirstCanUseRoutePath(restlist, path)
               if(this.redirect) { // 跳转到redirect页面
                 this.$router.push({ path: this.redirect , query: this.otherQuery })
               } else if(defPath){// 跳转到菜单的第一个页面
                 this.$router.push({ path: defPath, query: this.otherQuery })
               } else {
                  this.$router.push({ path: '/crm/', query: this.otherQuery })
               }
             },
             // 处理路由参数
             getOtherQuery(query) {
               return Object.keys(query).reduce((acc, cur) => {
                 if (cur !== "redirect" && cur !== "cas") {
                   acc[cur] = query[cur];
                 }
                 return acc;
              }, {});
            },
        }     
        
    }
</script>

2.permission.js中,进行全局前置路由守卫,本次新增的代码,主要是对无token时的补充处理

onst whiteList = ['/crm/login'] 
​
router.beforeEach(async (to, from, next) => {
    if(Vue.ls.get(ACCESS_TOKEN) {
       
     } else {
         if (whiteList.indexOf(to.path) !== -1) {
      next()
    } else {
      // 调整前的代码: next(`/crm/login`)
      // 调整后的代码
      next({ path: '/crm/login', query:  {redirect: to.path, ...to.query}})
      NProgress.done()
    }
    }
}

上述代码中,将to.path赋值给redirect,就是为了记录目标跳转页面,实现路由跳转需求1。

若目标跳转页面的query中,存在redirect,通过query: {redirect: to.path, ...to.query}写法,则redirect页面会覆盖to.path页面,实现路由跳转需求2。

而有token时,则需判断是否有routeList, 有则根据to.path及to.query.redirect跳转,没有则去获取routeList,再根据to.path及to.query.redirect跳转。逻辑相对简单,此处不在赘述。