vue 跨平台授权登录的实现

要想实现项目A授权登录到项目B,必须满足以下几个条件: ①项目A 需要有 项目B 的token,将token作为url参数进行跳转; ②项目B 开放与 login 同级的路径,不做拦截; ③项目B 从url中获取token,写入浏览器 Co...

这篇文章已从掘金同步到个人博客,原始发布地址为 掘金原文

要想实现项目A授权登录到项目B,必须满足以下几个条件:

①项目A 需要有 项目B 的token,将token作为url参数进行跳转;

②项目B 开放与 login 同级的路径,不做拦截;

③项目B 从url中获取token,写入浏览器 Cookies 后自动获取登陆信息,即可完成授权;

router/index.js
import Vue from "vue";
import Router from "vue-router";
/**
 * 不需要登录拦截的路由配置
 */
const loginIgnore = {
    names: ["404", "403"], // 根据路由名称匹配
    paths: ["/login", "/authorization"], // 根据路由fullPath匹配
    /**
     * 判断路由是否包含在该配置中
     * @param route vue-router 的 route 对象
     * @returns {boolean}
     */
    includes(route) {
        return this.names.includes(route.name) || this.paths.includes(route.path);
    }
};
/**
 * 初始化路由实例
 * @returns {VueRouter}
 */
function initRouter() {
    return new Router({
        mode: "history",
        routes: [{
            path: "/login",
            name: "login",
            meta: {
                title: "登录"
            },
            component: () => {
                return import("@/pages/login/LoginBlank");
            }
        },
        {
            path:"/start",
            name:"start",
            component: () => {
                return import("@/pages/StartView");
            }
        },
        {
            path: "/authorization",
            name: "authorization",
            meta: {
                title: "项目A授权登录项目B"
            },
            component: () => {
                return import("@/pages/authorization/Authorization");
            }
        },
        {
            path: "/404",
            name: "exp404",
            meta: {
                title: "404页面"
            },
            component: () => {
                return import("@/pages/exception/404");
            }
        },
        {
            path: "/500",
            name: "exp500",
            meta: {
                title: "500页面"
            },
            component: () => {
                return import("@/pages/exception/500");
            }
        },
        {
            path:"*",
            redirect: "/404"
        }]
    });
}

export {loginIgnore, initRouter};
router/guards.js
import { loginIgnore } from "@/router/index";

/**
 * 登录守卫
 * @param to
 * @param from
 * @param next
 * @param options
 */
const loginGuard = (to, from, next, options) => {
    const { message } = options;
    if (!loginIgnore.includes(to) && !checkAuthorization()) {
        message.warning("登录已失效,请重新登录");
        next({ path: "/login" });
    } else {
        //已登录,获取登录用户资料
        next();
    }
};

export default {
    beforeEach: [loginGuard]
};
/pages/authorization/Authorization

<template>
    <div class="authorize">
        <div class="authorize-top" style="background: #0074FE;">
            <img class="leftTopImg" src="https://gitee.com/lingxiu5858/assets/raw/master/img_authorize_rightBottom.png" alt="" />
            <span class="authorize-title">授权登录</span>
            <div class="authorize-content">
                <div class="logo">
                    <div class="leftLogo">
                        <img src="" alt="">
                        <div class="title">项目A</div>
                    </div>
                    <div class="animation">
                    </div>
                    <div class="rightLogo">
                        <img src="" alt="">
                        <div class="title">项目B</div>
                    </div>
                </div>
                <div class="container">
                    <div class="authorize-text">
                        <div class="tips">即将登录项目B</div>
                    </div>
                    <div class="authorize-operation">
                        <div><a-button type="primary" @click="confirm" style="width: 364px; height: 40px; background: #0074FE;">确定</a-button></div>
                        <div><a-button type="link"  @click="cancel" style="width: 364px; height: 40px; color: rgba(0,0,0,0.65);">返回</a-button></div>
                    </div>
                </div>
            </div>
            <img class="rightBottomImg" src="https://gitee.com/lingxiu5858/assets/raw/master/img_authorize_rightBottom.png" alt="" />
        </div>
        <div class="authorize-bottom"></div>
    </div>
</template>

<script>
import Cookies from "js-cookie";
import {getCurrentUser} from "@/services/authService/login";
import {requestError, requestFail} from "@/utils/request";

export default {
    name: "Authorization",
    components:{ BkLottie },
    data() {
        return {
            routeQuery: this.$route.query,
            userInfo: {}
        };
    },
    created() {
        this.getCookies();
    },
    mounted() {
    },
    methods: {
        getCookies(){
            let { accessToken } = this.routeQuery;
            console.log("routeQuery", accessToken);
            Cookies.set("Authorization", encodeURIComponent(accessToken)); // token
            this.toGetCurrentUser();
        },
        // 获取当前登录用户信息
        toGetCurrentUser(){
            getCurrentUser().then((res)=>{
                let{data} = res;
                if(data && data.success){
                    console.log("当前登录用户信息", data.result);
                    this.userInfo = data.result;
                }else{
                    requestFail(res, "");
                }
            }, requestError);
        },
        confirm(){
            location.replace("/");
        },
        cancel(){
            window.open("about:blank", "_self").close();
        }
    }
};
</script>
<style lang="less" scoped>
.authorize{
    margin: 0 auto;
    background: #FFFFFF;
    height: 100%;
    .authorize-top{
        width: 1920px;
        height: 464px;
        position: relative;
        border: 1px solid #979797;
        .leftTopImg{
            width: 249px;
            height: 204px;
        }
        .transparentLogo{
            position: absolute;
            top: 41px;
            width: 130px;
            height: 28px;
            margin-left: 61px;
        }
        .rightBottomImg{
            position: absolute;
            width: 631px;
            height: 371px;
            right: 0px;
            bottom: 0px;
        }
        .authorize-title{
            font-size: 32px;
            font-weight: 600;
            color: #FFFFFF;
            line-height: 45px;
            position: absolute;
            left: 45%;
            top: 25%;
        }
        .authorize-content{
            width: 586px;
            height: 620px;
            background: #FFFFFF;
            box-shadow: 0px 2px 20px 0px rgba(0,0,0,0.1);
            border-radius: 8px;
            position: absolute;
            left: 50%;
            top: 115%;
            transform: translate(-50%, -50%);
            .logo{
                margin: 104px 111px 0px 111px;
                display: flex;
                justify-content: center;
                align-items: center;
                .leftLogo, .rightLogo{
                    img{
                        width: 88px;
                        height: 88px;
                        margin-bottom: 8px;
                    }
                    .title{
                        font-size: 14px;
                        font-weight: 400;
                        color: rgba(0,0,0,0.85);
                        line-height: 20px;
                        text-align: center;
                    }
                }
                .animation{
                    margin: 0px 60px;
                }
            }
            .container{
                margin-top: 122px;
                display: flex;
                justify-content: center;
                align-items: center;
                flex-direction: column;
                .authorize-text{
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    flex-direction: column;
                    margin-bottom: 41px;
                    .tips{
                        font-size: 14px;
                        font-weight: 400;
                        color: rgba(0,0,0,0.45);
                        line-height: 20px;
                    }
                    .compName{
                        font-size: 16px;
                        font-weight: 600;
                        color: rgba(0,0,0,0.85);
                        line-height: 22px;
                    }
                }
            }
        }
    }
    .authorize-bottom{
    }
}
</style>