钉钉扫码登录(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;
});
相关推荐
Jmyd01233 小时前
Web端3D营销展厅技术实现路径:从素材上云到线索回流的数据链路
前端·3d·性能优化·三维数字化
半个落月3 小时前
LangChain Agent 中间件实战(上):生命周期、状态、短路与工具包
javascript·langchain
砚凝霜3 小时前
【软考信息安全】第二十二章 Web服务器安全分析与增强——Apache与IIS
服务器·前端·安全
半个落月3 小时前
LangChain Agent 中间件实战(下):DeepAgents文件权限、长期记忆与对话摘要
javascript·langchain
u0111026755 小时前
JPG、PNG、WebP 怎么选?按透明度、体积和使用场景做判断
前端·javascript·vue.js·图像处理·ai作画
jerrywus6 小时前
让 AI 写完代码后交一份报告:我改造了 answer-me-with-html
前端·claude·cursor
派小心.6 小时前
小程序分享链路中来源参数的传递校验
大数据·前端·数据库·人工智能·小程序·数据分析
hhb_6186 小时前
一键生成数据看板,ECharts实战演示
前端·javascript·echarts
Java后端的Ai之路7 小时前
08_React组件API
前端·react.js·前端框架
小马不起床7 小时前
零基础玩转 FastAPI_09:前端基础工程构建
前端·状态模式·fastapi