外部链接和VUE项目互相跳转实现退出登录

news2024/11/26 12:17:55

一、补坑总结提前说明
我的项目有一个前台MVC项目门户站点(用户登录信息存储在cookie),和后台vue项目(用户登录信息存储在localstorage)站点,2个站点分属不同的端口,那就是跨域了。之前我已经实现过了某个站点登录后,可以直接进入对方站点实现自动登录,也就是单点登录的效果,现在我要实现单点退出登录的效果,其实按理说原理跟登录是差不多的。参考之前写的单点登录跳转文章外部链接跳转到vue项目传递参数实现单点登录_吹牛不交税的博客-CSDN博客

但是我碰到了巨坑,折腾了我一天,大致总结如下:
http://localhost:9990//loginout?from=portal  昨天一直用的这个链接去跳转后台退出登录,但是到了后台之后,有个
const router = createRouter({
  history: myhistory, //createWebHistory(process.env.BASE_URL),
  routes
})
这里总是会人为的给链接路由换成/home。    然后我早上上厕所的时候想了一下之前登录成功跳转的链接,他是带了参了#/home/ 和参数过去,登录跳转可以,那我就把登录跳转的#/home/  放到前面,后面再加loginout和参数,变成下面这样,
http://localhost:9990/#/home/loginout?dXNlck5hbWU9dW5kZWZpbmVkJnVzZXJfSWQ9dW5kZWZpbmVkJmltZz11bmRlZmluZWQmdG9rZW49dW5kZWZpbmVk&from=portal
 他就不会直接把路由替换成 /home了,原因是啥我也不知道  ,createRouter 是vue内部函数,我昨天调试了很久都没调试出所以然。 
这策略就是变成了,我打不过他我就顺从他。

二、vue项目退出登录后跳转门户mvc项目的退出登录地址。

我的vue项目,原始退出登录的代码他就是一个函数调用store.commit('clearUserInfo', ''); 清除用户信息在前端的缓存,然后通过跳转跟路径"/"让系统自动判断重新跳转到登录路由就完事了。
那我现在想要在执行完跳转的时候还要跳转到别的站点链接,我就得单独做一个loginout的路由页面。

1、 loginout.vue路由文件代码,我开始尝试了想动态生成iframe,通过iframe的src属性执行外部链接,但是失败了,但是里面关于生成iframe的代码我没有删除,关于跳转最重要的几句就是下面的这几行。myhostname变量是站点根域名或者IP,http.portalUrl是端口(配置的门户站点端口),from=houtai用来告诉门户,是从后台跳转过去的请求,而且这里也有判断是否从门户跳转过来的链接(from=portal),如果是门户跳转过来的链接,就不能再跳转回去了,那就成了多次循环跳转了。

 let myhostname = location.hostname;
    let portal_loginout = "http://" + myhostname + ":" + http.portalUrl + "index/loginout?from=houtai";    
    if (location.href.indexOf("from=portal") < 0) {    
      location.href = portal_loginout;
    }

<template>
  <div id="divdom" ref="divdom">
    <!-- <iframe id="myframe"></iframe> -->
  </div>
</template>

<script>
import loading from "@/components/basic/RouterLoading";
import VolMenu from "@/components/basic/VolElementMenu.vue";
import Message from "./index/Message.vue";
import MessageConfig from "./index/MessageConfig.js";

import {
  defineComponent,
  reactive,
  ref,
  watch,
  onMounted,
  getCurrentInstance,
} from "vue";
import { useRouter, useRoute } from "vue-router";
import store from "../store/index";
import http from "@/../src/api/http.js";
import { HttpResponse } from "@microsoft/signalr";
import base64 from 'js-base64';
const jsBase64 = require('js-base64').Base64; //js-base64 加密

export default defineComponent({
  components: {

  },

  data() {
    return {

      //  contextMenuVisible: false, // 右键关闭显/隐
    };
  },
  setup(props, context) {
    store.commit('clearUserInfo', '');
    const loading = ref(false);
    const codeImgSrc = ref('');
    const userInfo = reactive({
      userName: '',
      password: '',
      verificationCode: '',
      UUID: undefined
    });
    let appContext = getCurrentInstance().appContext;
    let $message = appContext.config.globalProperties.$message;
    let router = useRouter();
    $message.success('退出成功,正在跳转!');

    return {
      loading,
      codeImgSrc,
      userInfo,
    };
  },
  /**
   * 挂载钩子函数
   */
  mounted() {
    // alert("111");
    // debugger;
    let myhostname = location.hostname;
    let portal_loginout = "http://" + myhostname + ":" + http.portalUrl + "index/loginout?from=houtai";
    // alert(portal_loginout);
    let mydom = this.$refs.divdom;       
    if (location.href.indexOf("from=portal") < 0) {
      // this.createIframe(mydom, portal_loginout, null);
      location.href = portal_loginout;
    }
  },

  methods: {

    /**
    * 动态创建iframe
    * @param dom 创建iframe的容器,即在dom中创建iframe。dom能够是div、span或者其它标签。
    * @param src iframe中打开的网页路径
    * @param onload iframe载入完后触发该事件。能够为空
    * @return 返回创建的iframe对象
    * */
    createIframe(dom, src, onload) {
      //在document中创建iframe
      var iframe = document.createElement("iframe");
      //设置iframe的样式
      iframe.style.width = "100%";
      iframe.style.height = "100%";
      iframe.style.margin = "0";
      iframe.style.padding = "0";
      iframe.style.overflow = "hidden";
      iframe.style.border = "none";
      //绑定iframe的onload事件,处理事件的兼容问题
      if (onload && Object.prototype.toString.call(onload) === "[object Function]") {
        if (iframe.attachEvent) {
          iframe.attachEvent("onload", onload);
        }
        else if (iframe.addEventListener) {
          iframe.addEventListener("load", onload);
        }
        else {
          iframe.onload = onload;
        }
      }
      iframe.src = src;
      //把iframe载入到dom以下
      dom.appendChild(iframe);
      return iframe;
    },


  },
  created() {

  },
  /**
   * 销毁钩子函数
   */
  destroyed() {
    $this = null;
    clearInterval($interval);
  },
});
</script>

2、 router/index.js 路由配置文件中,增加一个路由

{

    path: '/loginout',

    name: 'loginout',

    component: () => import('@/views/Loginout.vue'),

    redirect: '/loginout',

    meta: {

      anonymous: true

    }

  },

 这个文件下面还有一个位置router.beforeEach 的时候要增加以下判断  

if(to.fullPath.indexOf("loginout")>0)

  {  

    return next();   

  }

 

3、在退出登录按钮执行的代码位置,加一行代码跳转到loginout路由

 三、门户MVC项目退出登录,然后跳转到后台vue项目的路由

1、退出登录按钮位置的代码

2、loginout路由的后端代码没有写什么东西,就将config配置的后端跳转路由啥的读取存到ViewBag。

ViewBag.adminUrl = _adminUrl;
            ViewBag.portapiurl = _portapiurl;
            return View();

3、loginout.cshtml 文件代码   

重点代码段:

 var cookietokenvalue = $.cookie('portalusertoken');
        var cookieusername = $.cookie('portalusername');
        var portaluserid = $.cookie('portaluserid');
        var portalimg = $.cookie('portalimg'); 
        var portapiurl = $.cookie('_portapiurl');

        var adminUrl = getCookie('_adminUrl');
        adminUrl = $("#hid_adminurl").val() ;

        var myurlhouzhui = "/loginout?" + Base64.encode("userName=" + encodeURI(cookieusername) + "&user_Id=" + portaluserid + "&img=" + portalimg + "&token=" + cookietokenvalue)+"&from=portal";
        if (adminUrl != undefined && adminUrl != null && adminUrl != "null" && adminUrl != "" && location.href.indexOf("&from=houtai") < 0) {
            var myhostname = location.hostname;
            var myadmin_arr = adminUrl.split("%2F");
            var portal_loginout = "http://" + myhostname + ":" + adminUrl + myurlhouzhui;   //"/loginout?from=portal"
            //alert(portal_loginout);
            //var mydom = $("#divdom");
            //var mydom = document.querySelector("divdom");
            //this.createIframe(mydom, portal_loginout, null);
            debugger;
            window.location.href = portal_loginout;
            //window.open(portal_loginout);
        }

@*
    For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
*@
@{
    Layout = "_Layout.cshtml";
}

<html lang="zh-CN">

<head>

    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta property="og:title" content="Digital Marketplace Template" />
    <meta property="og:type" content="website" />
    <meta property="og:url" content="" />
    <meta property="og:image" content="" />

    <link rel="stylesheet" href="~/portal/assets/css/preloader.css" />
    <script src="~/portal/assets/js/preloader.js"></script>


    <link rel="stylesheet" href="~/portal/assets/css/vendor/bootstrap.min.css" />
    <link rel="stylesheet" href="~/portal/assets/css/vendor/nice-select.css" />
    <link rel="stylesheet" href="~/portal/assets/css/vendor/magnific-popup.css" />
    <link rel="stylesheet" href="~/portal/assets/css/vendor/slick.css" />
    <link rel="stylesheet" href="~/portal/assets/css/vendor/aos.css" />
    <link rel="stylesheet" href="~/portal/assets/css/style.css" />
    <title>造价师服务平台</title>

    <script src="~/portal/assets/js/vendor/jquery.min.js"></script>
    <script src="~/portal/assets/js/vendor/jquery.nice-select.min.js"></script>
    <script src="~/portal/assets/js/jquery.cookie.min.js"></script>

    <script src="~/Scripts/My97DatePicker/WdatePicker.js"></script>
    <script src="~/js/js-base64-3.7.5/package/base64.js"></script>

</head>
<body> 
    <div id="divdom" ref="divdom">
        <!-- <iframe id="myframe"></iframe> -->
    </div>

    <input type="hidden" id="hid_adminurl" value="@ViewBag.adminUrl" />
    <input type="hidden" id="hid_portapiurl" value="@ViewBag.portapiurl" />

    <script>
        /**
        * 动态创建iframe
        * param dom 创建iframe的容器,即在dom中创建iframe。dom能够是div、span或者其它标签。
        * param src iframe中打开的网页路径
        * param onload iframe载入完后触发该事件。能够为空
        * return 返回创建的iframe对象
        * */
        function createIframe(dom, src, onload) {
            //在document中创建iframe
            var iframe = document.createElement("iframe");
            //设置iframe的样式
            iframe.style.width = "100%";
            iframe.style.height = "100%";
            iframe.style.margin = "0";
            iframe.style.padding = "0";
            iframe.style.overflow = "hidden";
            iframe.style.border = "none";
            //绑定iframe的onload事件,处理事件的兼容问题
            if (onload && Object.prototype.toString.call(onload) === "[object Function]") {
                if (iframe.attachEvent) {
                    iframe.attachEvent("onload", onload);
                }
                else if (iframe.addEventListener) {
                    iframe.addEventListener("load", onload);
                }
                else {
                    iframe.onload = onload;
                }
            }
            iframe.src = src;
            //把iframe载入到dom以下
            dom.appendChild(iframe);
            return iframe;
        }
         
        /**
        *设置 cookie 值的函数,创建一个函数用于存储访问者的名字
        *cname:名称,必须字母
        *cvalue:值
        *exdays:过期时间(天)
        * */
        var setCookie = function (cname, cvalue, exdays) {
            var d = new Date();
            d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
            var expires = "expires=" + d.toGMTString();
            document.cookie = cname + "=" + cvalue + "; " + expires + ";path=/";
        };
         

        //获取 cookie 值的函数,创建一个函数用户返回指定 cookie 的值
        //cname:名称,你之前设置的名称
        var getCookie = function (cname) {
            var name = cname + "=";
            var ca = document.cookie.split(';');
            for (var i = 0; i < ca.length; i++) {
                var c = ca[i].trim();
                if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
            }
            return null;
        };

       

        
        $.ajax({
            type: "get",
            url: "/index/tologinout",
            async: false,
            success: function (res) {
                debugger;
                $.cookie("portalusertoken", null, { path: '/', expires: -1 }); //删除hello
                $.cookie("portalusername", null, { path: '/', expires: -1 }); //删除hello
                $.cookie("portaluserid", null, { path: '/', expires: 10 }); //删除hello
                $.cookie("portalimg", null, { path: '/', expires: 10 }); //删除hello
                //重新指向首页
                var myhostname = location.hostname;
                var port = window.location.port;
                var myindexurl = "http://" + myhostname + ":" + port + "/index/index";
                location.href = myindexurl;
            }
        });
        $.cookie("portalusertoken", null, { path: '/', expires: -1 }); //删除hello
        $.cookie("portalusername", null, { path: '/', expires: -1 }); //删除hello
        $.cookie("portaluserid", null, { path: '/', expires: -1 }); //删除hello
        $.cookie("portalimg", null, { path: '/', expires: -1 }); //删除hello
        //重新指向首页
        //var myhostname = location.hostname;
        //var port = window.location.port;
        //var myindexurl = "http://" + myhostname + ":" + port + "/index/index";
        //location.href = myindexurl;

        var cookietokenvalue = $.cookie('portalusertoken');
        var cookieusername = $.cookie('portalusername');
        var portaluserid = $.cookie('portaluserid');
        var portalimg = $.cookie('portalimg'); 
        var portapiurl = $.cookie('_portapiurl');

        var adminUrl = getCookie('_adminUrl');
        adminUrl = $("#hid_adminurl").val() ;

        var myurlhouzhui = "/loginout?" + Base64.encode("userName=" + encodeURI(cookieusername) + "&user_Id=" + portaluserid + "&img=" + portalimg + "&token=" + cookietokenvalue)+"&from=portal";
        if (adminUrl != undefined && adminUrl != null && adminUrl != "null" && adminUrl != "" && location.href.indexOf("&from=houtai") < 0) {
            var myhostname = location.hostname;
            var myadmin_arr = adminUrl.split("%2F");
            var portal_loginout = "http://" + myhostname + ":" + adminUrl + myurlhouzhui;   //"/loginout?from=portal"
            //alert(portal_loginout);
            //var mydom = $("#divdom");
            //var mydom = document.querySelector("divdom");
            //this.createIframe(mydom, portal_loginout, null);
            debugger;
            window.location.href = portal_loginout;
            //window.open(portal_loginout);
        }

    </script>
</body>


</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/938805.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux 桌面上的 Firefox 面临着大问题

导读毫无疑问&#xff0c;无论是在桌面、笔记本电脑还是移动设备上&#xff0c;浏览器都是任何操作系统中最重要的应用之一。 如果没有一个功能强大、快速且稳定的浏览器&#xff0c;操作系统的实用性将大幅度降低&#xff0c;以至于我相当确定&#xff0c;如果一个操作系统没有…

C语言二——依次将10个数输入,要求将其中最大的数输出

这是一个简单的C语言程序&#xff0c;它会接受用户输入的10个整数&#xff0c;然后找出最大值并输出。 程序的执行步骤如下&#xff1a; 声明一个数组 n&#xff0c;用于存储用户输入的10个整数&#xff0c;声明一个变量 i 和 t。提示用户输入10个数。使用 for 循环&#xff…

Face2Face: Real-time Face Capture and Reenactment of RGB Videos (CVPR 2016) 译文

建议的在线再现设置:单目目标视频序列(例如&#xff0c;来自Youtube)基于源演员的表达进行再现&#xff0c;源演员使用商品网络摄像头进行现场录制。 摘要 我们提出了一种用于单目目标视频序列(例如Youtube视频)的实时面部再现的新方法。源序列也是单目视频流&#xff0c;用商…

小红书口碑营销技巧有哪些,打造独特品牌内容

作为一款社交电商平台&#xff0c;从目前来看&#xff0c;其实小红书也算是比较不错的口碑营销传播平台了。今天就来带大家一起分享下&#xff0c;小红书口碑营销技巧有哪些&#xff0c;打造独特品牌内容&#xff01; ​ 一、小红书口碑营销怎么做 1. 了解目标用户 首先需要明…

不到3个月,快速上线联创三金MES系统,数字化生产管理初见成效

PART 01 MES系统上线 8月25日&#xff0c;惠州联创三金科技有限公司&#xff08;下文简称联创三金&#xff09;顺利举行了MES系统上线仪式&#xff0c;这标志着联创三金正式运行全新的数字化生产管理系统&#xff0c;迈向了生产管理全面透明化的新阶段。联创集团IT总监邓燕琼…

【Vue3】Pinia状态管理

Pinia pinia与Vuex的对比pinia的介绍pinia与Vuex区别&#xff1a;pinia的使用使用准备步骤一&#xff1a;新建文件导入pinia使用准备步骤二&#xff1a;挂载pinia 创建pinia的Store新建页面。创建对应的Store页面使用pinia的store Pinia核心概念State操作State一重置state改变s…

SciencePub学术 | 计算机智能类重点SCIEEI征稿中

SciencePub学术 刊源推荐: 计算机智能类重点SCIE&EI征稿中&#xff01;信息如下&#xff0c;录满为止&#xff1a; 一、期刊概况&#xff1a; 计算机智能类重点SCIE&EI 【期刊简介】IF&#xff1a;1.0-1.5&#xff0c;JCR4区&#xff0c;中科院4区&#xff1b; 【检…

Google Play商店优化排名因素之应用标题

对于用户数量和应用数量而言&#xff0c;Google Play 商店是最大的应用商店。市场巨大&#xff0c;同时机遇也巨大。然而由于有近 250 万个应用程序&#xff0c;竞争也同样激烈。 1、应用程序标题是所有排名因素中最强的。 与Apple的30个字符限制相反&#xff0c;Google Play商…

初识Java 1-1 面向对象的语言

目录 引用的作用 数据的储存 常见的数据储存方式 特殊储存的基本类型 数组 销毁对象 基本类型的作用域 对象的作用域 创建新类型 - class关键字 方法、参数和返回值 参数列表 编写程序 名称可见性 使用组件 static关键字 Java程序 编程风格&#xff08;驼峰式…

SAP从放弃到入门系列之abapGit更新与卸载

目录概览 概述一、更新1.1 独立版本1.2 开发者版本1.2.1 在线更新1.2.2 离线更新 1.3 更新版本常见问题 二、卸载abapGit 概述 我们就以更新abapGit为例,通过abapGit管理我们的代码其实操作时相似的&#xff0c;更新独立版本就有点像最原始的没有版本管理工具时的版本管理方式…

Elasticsearch中倒排索引、分词器、DSL语法使用介绍

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…

研磨设计模式day14模板方法模式

目录 场景 原有逻辑 有何问题 解决方案 解决思路 代码实现 重写示例 模板方法的优缺点 模板方法的本质 何时选用 场景 现在模拟一个场景&#xff0c;两个人要登录一个系统&#xff0c;一个是管理员一个是用户&#xff0c;这两个不同身份的登录是由后端对应的两个接…

Metasploit“MSF”连接postgresql时因排序规则版本不匹配导致无法连接

一、问题 更新Kali之后使用Metasploit时出现一个问题&#xff0c;连接postgresql时因排序规则版本不匹配导致无法连接 警告: database "msf" has a collation version mismatch DETAIL: The database was created using collation version 2.36, but the operati…

SpringBoot使用Druid连接池 + 配置监控页面(自定义版 + starter版)

目录 1. Druid连接池的功能2. 自定义版2.1 pom.xml添加依赖2.2 MyDataSourceConfig实现2.3 application.properties配置编写Controller进行测试2.4 druid监控页面查看 3. starter版3.1 pom.xml添加依赖3.2 自动配置分析3.3 使用application.properties对druid进行配置3.4 druid…

Git分支机制

一、分支机制简述 要想真正理解Git的分支机制&#xff0c;我们要首先回过头来看一下Git是如何存储数据的。 Git并没有采用多个变更集( changeset )或是差异的方式存储数据&#xff0c;而是采用一系列快照的方式。当你发起提交时&#xff0c;Git存储的是提交对象( commi…

无涯教程-机器学习 - 箱形图函数

Box和Whisker图(也简称为boxplots)是另一种有用的技术&#xff0c;可用于检查每个属性的分布情况。以下是此技术的特点- 它本质上是单变量的&#xff0c;总结了每个属性的分布。它为中间值(即中位数)画一条线。它将在25&#xff05;和75&#xff05;周围绘制一个框。它还会绘制…

ant-vue1.78版a-auto-complete表单自动搜索返回列表中的关键字标红

a-auto-complete表单自动搜索返回列表中的关键字标红 通常在做关键字标红的场景&#xff0c;都是后端返回html结构&#xff0c;前端直接渲染实现&#xff0c;但是如果需要前端处理的话&#xff0c;实现也是很简单的&#xff0c;接下来我直接上应用场景吧 应用场景就是通过关键…

mysql 存储引擎系列 (一) 基础知识

当前支持存储引擎 show engines&#xff1b; 显示默认存储引擎 select default_storage_engine; show variables like ‘%storage%’; 修改默认引擎 set default_storage_enginexxx 或 set default_storage_enginexxx; my.ini 或者 my.cnf ,需要重启 服务才能生效 systemctl …

什么事synchronized的升级

今天我们继续学习synchronized的升级过程&#xff0c;目前只剩下最后一步了&#xff1a;轻量级锁->重量级锁。 通过今天的内容&#xff0c;希望能帮助大家解答synchronized都问啥&#xff1f;中除锁粗化&#xff0c;锁消除以及Java 8对synchronized的优化外全部的问题。 获…

校招算法题实在不会做,有没有关系?

文章目录 前言一、校招二、时间复杂度1、单层循环2、双层循环 三、空间复杂度四、数据结构五、校招算法题实在不会做&#xff0c;有没有关系&#xff1f;六、英雄算法集训 前言 英雄算法联盟八月集训 已经接近尾声&#xff0c;九月算法集训将于 09月01日 正式开始&#xff0c;目…