VUE实现跨平台登录

1,482 阅读3分钟

背景

这次迭代有个很有意思的需求,描述很简单就是我方平台发送链接到其他平台,其他平台点链接能实现无感登录到我方平台。重点来了,登录成功而且要无感。

1.如何实现登录?

首先我们来思考一个问题,为什么无法直接跳转?

要想弄清楚这个问题,我们就要思考当我们打开一个链接的时候,我们自身的框架都为我们做了什么处理? 熟悉vue的人都知道路由前置守卫,没错进入页面时会触发router.beforeEach的钩子,你可以把他理解成通往成功跳转的必经之路

那在这个钩子里框架做了什么事呢?

a.首先页面会判断有没有登录过帐号,判断有没有登录过帐号的方式一般都是看看本地有没有存储token。这个token我们可以理解为一个登录过后得到的身份证,有了这个身份证你就可以畅通无阻,在任何界面自由穿梭。

b.有token则成功跳转,没token则跳转到登录页面。

是否登录.png

了解这些我们就知道其实只要能有一个token,就能实现我们的目的。ok接下来我们就想想怎么去获得这个token?

2.如何获取token?

获取token的方式最直接的方式其实就是后台直接把token当作参数放到链接中,用户点击链接,前端直接获取浏览器的参数token存放到本地。但是这样做有一个弊端:这个token是有过期时间的,一旦过期还是会跳转到登录页面。所以最佳实践还是得每次跳转都手动去获取一个最新的token。

如何获取最新token?要么调登录接口,传入用户名和密码获取最新token,要么就是直接传一个用户名和密码生成的加密字符串,传给后台解析再返回一个最新token,这两种方式都可以达到目的。

ok接下来就直接上代码,最开始我写的如下图所示:

router.beforeEach((to, from, next) => {
    //是否有自动登录,通过跳转链接是否携带token参数来判断
    if(!!(to.query.token)){
        // 调用接口获取token,并存储到本地
    }
    // 检测本地是否存储token
    if (localStorage.getItem('token')) {
        // 调用接口获取用户信息等
    }
}

但是上面的代码会有一个问题就是并非同步执行,因为调用接口获取token是异步操作。变成同步也很简单,这里就不过多赘述。

export const init=(callback)=>{
    // 调用接口获取token
    // 调用接口获取用户信息等
    callback()
}
import init from ".."
router.beforeEach((to, from, next) => {
    // 检测是否有自动登录或者本地是否存储token
    if (!!(to.query.token)||localStorage.getItem('token')) {
       init(callback) 
    }
}

3.优化

3.1 到这其实基本就已经实现功能了,但是有强迫症和完美主义的朋友一定会发现,你跳转过来的链接会多一些参数。看着很别扭而且搞不好还存在一定的风险。如何去除呢?很简单

// 去掉地址栏的token参数
if (Reflect.has(to.query, 'token')) {
    Reflect.deleteProperty(to.query, 'token');
}
// 使用replace是因为不想返回的时候跳转到登录页面,因为直接next路由记录里会留存登录路径
next({ ...to, replace: true });

3.2 如果我是说如果,你的页面头部会有返回按钮的,比如一些详情页面头部往往会有返回按钮。这个时候由于是直接跳转过来的,路由记录里只存在你当前页面的一条记录,所以你的返回按钮点击是无效的。这个你可以仔细看浏览器的返回按钮,浏览器返回按钮是禁用的就说明没法回退。这个也有两种解决方法:要么也禁用返回按钮,要么就是判断如果无法回退就跳转到某一个指定链接

if (window.history.length > 1) {
    this.$router.go(-1); // 返回上一个界面
} else {
    this.$router.push({
        path: 'xx',
    });
}