钉钉扫码登录(DTFrameLogin) 用户注销后重新登录出现回调叠加的问题

dd-login.js源码

javascript 复制代码
! function(e) {
	var t = {};

	function r(n) {
		if (t[n]) return t[n].exports;
		var o = t[n] = {
			i: n,
			l: !1,
			exports: {}
		};
		return e[n].call(o.exports, o, o.exports, r), o.l = !0, o.exports
	}
	r.m = e, r.c = t, r.d = function(e, t, n) {
		r.o(e, t) || Object.defineProperty(e, t, {
			enumerable: !0,
			get: n
		})
	}, r.r = function(e) {
		"undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {
			value: "Module"
		}), Object.defineProperty(e, "__esModule", {
			value: !0
		})
	}, r.t = function(e, t) {
		if (1 & t && (e = r(e)), 8 & t) return e;
		if (4 & t && "object" == typeof e && e && e.__esModule) return e;
		var n = Object.create(null);
		if (r.r(n), Object.defineProperty(n, "default", {
			enumerable: !0,
			value: e
		}), 2 & t && "string" != typeof e)
			for (var o in e) r.d(n, o, function(t) {
				return e[t]
			}.bind(null, o));
		return n
	}, r.n = function(e) {
		var t = e && e.__esModule ? function() {
			return e.default
		} : function() {
			return e
		};
		return r.d(t, "a", t), t
	}, r.o = function(e, t) {
		return Object.prototype.hasOwnProperty.call(e, t)
	}, r.p = "", r(r.s = 1382)
}({
	1382: function(e, t) {
		var r = function(e, t) {
			var r = e.match(new RegExp("[?&]" + t + "=([^&]+)"));
			return r ? r[1] : null
		};
		window.DTFrameLogin = function(e, t, n, o) {
			var i, u = e.id && document.getElementById(e.id) || null,
				c = document.createElement("iframe");
			t.client_id && t.redirect_uri && t.response_type && t.scope ? u ? (u.innerHTML = "", u.appendChild(c), c && c.contentWindow && c.contentWindow.postMessage && window.addEventListener ? (c.src = "https://" + ((i = t)
				.isPre ? "pre-login" : "login") + ".dingtalk.com/oauth2/auth?iframe=true&redirect_uri=" + i.redirect_uri + "&response_type=" + i.response_type + "&client_id=" + i.client_id + "&scope=" + i.scope + (i.prompt ? "&prompt=" + i.prompt : "") + (i.state ? "&state=" + i.state : "") + (i.org_type ? "&org_type=" + i.org_type : "") + (i.corpId ? "&corpId=" + i.corpId : "") + (i.exclusiveLogin ? "&exclusiveLogin=" + i.exclusiveLogin : "") + (i.exclusiveCorpId ? "&exclusiveCorpId=" + i.exclusiveCorpId : ""), c.width = "" + (e.width || 300), c.height = "" + (e.height || 300), c.frameBorder = "0", c.scrolling = "no", window.addEventListener("message", (function(e) {
				var t = e.data,
					i = e.origin;
				if (/login\.dingtalk\.com/.test(i) && t)
					if (t.success && t.redirectUrl) {
						var u = t.redirectUrl,
							c = r(u, "authCode") || "",
							d = r(u, "state") || "",
							s = r(u, "error") || "";
						c ? n && n({
							redirectUrl: u,
							authCode: c,
							state: d
						}) : o && o(s)
					} else o && o(t.errorMsg)
			}))) : o && o("Browser not support")) : o && o("Element not found") : o && o("Missing parameters")
		}
	}
});

在源码中注册了 window.addEventListener("message",fn)事件但是没有 在适当的时候注销掉该事件可能会出现回调函数多次执行的问题。

一般的话可以使用具名函数,或者在页面卸载的时候取消监听器。

javascript 复制代码
window.addEventListener("beforeunload", function() {
  window.removeEventListener("message", messageHandler);
});

下面是钉钉扫码多次回调的解决方案

javascript 复制代码
// 业务代码登录的回调函数
let doLoginByDD = (authCode: string) => {
  // 这里可以直接进行重定向
  // window.location.href = redirectUrl;
  // 也可以在不跳转页面的情况下,使用code进行授权
  useUserStoreHook()
    .loginBydingdingScan({
      code: authCode
    })
    .then(r => {
      if (r.code === 200) {
        // 获取后端路由
        initRouter().then(() => {
          router.push(getTopMenu(true).path);
          message("登录成功", { type: "success" });
          doLoginByDD = null;//登录成功后清空函数
        });
      }
    });
};
const ddLoginInit = () => {
  (window as any).DTFrameLogin(
    {
      id: "dingdingLoginFrame",
      width: 300,
      height: 300
    },
    {
      redirect_uri: encodeURIComponent(VITE_DINGDING_REDIRECT_URI),
      client_id: "你的钉钉ClienId",
      scope: "openid",
      response_type: "code",
      state: "xxxxxxxxx",
      prompt: "consent"
    },
    loginResult => {
      const { redirectUrl, authCode, state } = loginResult;
       // 这个回调下,用户登录成功后,退出,再次重新登录,会出现回调叠加。
      if (doLoginByDD) {
        doLoginByDD(authCode);
      }
    },
    errorMsg => {
      // 这里一般需要展示登录失败的具体原因,可以使用toast等轻提示
      console.error(`errorMsg of errorCbk: ${errorMsg}`);
    }
  );
//页面卸载 清空掉回调函数
onBeforeUnmount(() => {
  doLoginByDD = null;
});
相关推荐
恋猫de小郭1 小时前
AGENTS.md 真的对 AI Coding 有用吗?或许在此之前你没用对?
前端·人工智能·ai编程
sunny_2 小时前
构建工具的第三次革命:从 Rollup 到 Rust Bundler,我是如何设计 robuild 的
前端·rust·前端工程化
rfidunion3 小时前
springboot+VUE+部署(12。Nginx和前端配置遇到的问题)
前端·vue.js·spring boot
珹洺4 小时前
Java-servlet(五)手把手教你利用Servlet配置HTML请求与相应
java·运维·服务器·前端·servlet·html·maven
FYKJ_20104 小时前
springboot大学校园论坛管理系统--附源码42669
java·javascript·spring boot·python·spark·django·php
QQ24391974 小时前
语言在线考试与学习交流网页平台信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
前端·spring boot·sql·学习·java-ee
范特西.i4 小时前
QT聊天项目(6)
前端
a1117764 小时前
水体渲染系统(html开源)
前端·开源·threejs·水体渲染
程序员小李白5 小时前
CSS 盒子模型
前端·css·html
Zzz不能停5 小时前
单行 / 多行文本显示省略号(CSS 实现)
前端·css