钉钉扫码登录(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;
});
相关推荐
竹林8186 分钟前
用 The Graph 查询链上数据实战:从手搓 RPC 到 Subgraph,我的 NFT 项目数据加载快了 10 倍
前端·javascript
妙码生花23 分钟前
从 PHP 到 AI + Golang,程序员自救转型手记(十九):点选验证码代码逐行目检
前端·后端·go
Awu12271 小时前
⚡从零开发 Agent CLI(五)实现一个可治理、可扩展的工具系统
前端·人工智能·claude
咪库咪库咪2 小时前
Vue3-生命周期
前端
莪_幻尘2 小时前
你的 AI Skill 越多越蠢?Token 上下文爆炸的求生指南
前端·ai编程
lichenyang4532 小时前
从 has.echo 到异步 API 注册表:一次 ASCF API 回调不触发的排查复盘
前端
林瞅瞅3 小时前
Nuxt3 项目部署 Nginx 防盗链后特定 JS 文件 403 问题修复方案
前端
kyriewen3 小时前
别再每次都 Google 了:我整理了前端日常最常踩的 10 个 Git 坑,附速查表
前端·javascript·git
一颗奇趣蛋3 小时前
Web 视频开发完全指南:从入门到精通
前端
非洲农业不发达3 小时前
windows终端体验大升级,让你拥有macos级别的美化
前端·后端