当前位置: 首页 > article >正文

钉钉实现第三方登录示例(重复回调问题解析)

钉钉作为专门为企业打造的沟通协助平台,包含的功能很多,考勤打卡,审批,日记,钉盘,钉邮等。基本满足了一些中小企业的大部分工作需求。因此对接钉钉的一些功能模块业务需求在开发中也是比较常见的。钉钉的开发文档很多,因为功能多再加上文档的迭代,新旧更替,有时候你想对接某个模块功能,没准连找个文档都要半天呢

1.准备工作

        正所谓工欲善其事必先利其器,本博文主要对接的是钉钉授权第三方登录,因此先找到对应的官方文档,根据文档熟悉流程。

实现登录第三方网站:实现登录第三方网站 - 钉钉开放平台

 步骤一和步骤二就不多加叙述了,完成后要拿到应用的Client ID,以及完成步骤四在应用的安全配置中完成重定向域名配置。

 2.钉钉扫码授权登录

        这里演示代码直接用单html吧,能否快速看到效果:

ddqrcode.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>钉钉扫码登录测试</title>
    <script src="https://g.alicdn.com/dingding/h5-dingtalk-login/0.21.0/ddlogin.js"></script>
    <script src="https://cdn.staticfile.net/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
    <div class="form-container">
        <h3 style="margin: 0 auto;text-align: center;margin-bottom: 30px;">钉钉扫码登录演示</h3>
        <div id="self_defined_element" class="self-defined-classname"></div>
    </div>
</body>
</html>
<script>
    // STEP3:在需要的时候,调用 window.DTFrameLogin 方法构造登录二维码,并处理登录成功或失败的回调。
    window.DTFrameLogin(
        {
            id: 'self_defined_element',
            width: 300,
            height: 300,
        },
        {
            redirect_uri: encodeURIComponent('http://你的回调地址'),
            client_id: 'ding97xxxxxx',
            scope: 'openid',
            response_type: 'code',
            state: 'dream',
            prompt: 'consent',
        },
        (loginResult) => {
            const {redirectUrl, authCode, state} = loginResult;
            console.log('loginResult:', loginResult);
            $.ajax({
                url:`http://你的回调地址?authCode=${authCode}&state=${state}`,
                method:'get',
                contentType:'application/json',
                dataType:'json',
                success:function(data) {
                    if(data.code == 0) {
                    	console.log("登录成功:",data);
                    }else {
                        alert(data.msg);
                        return;
                    }
                },
                error: function(err){
                    alert(err);
                }
            });
        },
        (errorMsg) => {
            // 这里一般需要展示登录失败的具体原因,可以使用toast等轻提示
            console.error(`errorMsg of errorCbk: ${errorMsg}`);
        },
    );
</script>
<style>
    body {
    font-family: 'Arial', sans-serif;
    background-color: #f4f4f4;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
}
.self-defined-classname {
        width: 300px;
        height: 300px;
    }
</style>

这里引入了钉钉sdk ddlogin.js,直接无脑调用,填写对应的回调地址和client_id就行了,回调后拿到authCode请求到后端登录接口。这里可能有人产生疑问了?不是还有步骤3内网穿透吗?

好消息是:调用钉钉扫码授权登录第三方网站,支持内网情况下的回调,不用考虑什么内网穿透。

坏消息是:构建授权链接实现授权登录需要内网穿透,也就是必须外网能访问。

3.构造授权链接登录

        钉钉的授权登录第三方网站的方式有两种,上面的那种属于调用钉钉sdk生成内嵌二维码,用钉钉app扫码后实现登录,扫完后二维码就失效了。适合作为登录用。

        但是还有一种情况,假如需求是利用钉钉扫码授权实现第三方网站的签到呢,同时多人扫同一个二维码的情况。

        这里就要用到第二种,通过构造授权链接。因为授权链接构造后就是一直有效的,我们可以将授权链接转化为二维码,提供给用户扫码,用户用钉钉app扫码后就相当于打开了授权链接,会触发钉钉的内部授权,点击授权后会直接重定向回调到我们配置的页面。因为是钉钉内打开的页面,所以回调的地址一定要是线上的。这也是为什么要内网穿透的原因。当然,如果我们有一个线上的域名及站点,也可以实现测试。

比如,lz构造了如下登录链接:

线上回调地址是:https://liuqingwushui.top/qrcodeauth.html (别忘了钉钉应用配置一下)

https://login.dingtalk.com/oauth2/auth?redirect_uri=https%3A%2F%2Fliuqingwushui.top%2Fqrcodeauth.html&response_type=code&client_id=ding97xxxxx&scope=openid&state=dream&prompt=consent

lz将这个路径手动转化为二维码供用户扫码。然后再写一个qrcodeauth.html 页面来接收回调的参数。

qrcodeauth.html回调页面接收参数并打印:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录回调显示页面</title>
    <script src="https://cdn.staticfile.net/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
    <div id="params-output">
        <!-- 路径参数将在这里显示 -->
    </div>
</body>
 <script>
        // 获取当前URL的路径部分
        const path = window.location.pathname;
        const searchParams = new URLSearchParams(window.location.search);

        // 解析路径参数
        const params = {};
        searchParams.forEach((value, key) => {
            params[key] = value;
        });

        // 将参数转换为字符串
        const paramsString = JSON.stringify(params, null, 2);

        // 使用jQuery将参数输出到HTML中
        $('#params-output').html('<pre>' + paramsString + '</pre>');
    </script>
</html>

        不通的用户扫码授权回调的authCode,我们在这个页面做接收处理即可,为了区别扫码来源,可以利用state做动态参数区分。如此,我们就实现了一个二维码供多个钉钉用户扫码实现签到的功能了。

4.扫码重复调用回调函数问题

        在vue中调用钉钉登录扫码,会发现重复调用的问题,然后就出现401错误,提示失效。因为前面说了,每个二维码只能扫一次。这种情况是因为钉钉官方sdk中window.addEventListener 监听iframe 触发多次导致的,经过测试对比,发现直接改ddlogin.js 源码是最有效的。

        将源码下载下来本地引用,然后更改:

//源代码块
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.onmessage = 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监听改成window.onmessage。

4.小结

        总而言之,言而总之。在对接一些第三方时,核心要点就是去熟悉理解他们的开发文档,但是谁也不知道明天你要对接的第三方会是谁?这也是lz的博文对于技术这块都喜欢力求细致,通俗易懂,能达到上手即看效果,下手即能用的程度。

        


http://www.kler.cn/a/504407.html

相关文章:

  • C++复习
  • RuoYi-Vue-Plus 加入 GitCode:驱动多租户后台管理创新发展
  • 后端技术选型 sa-token校验学习 下 结合项目学习 后端鉴权
  • 第423场周赛:检测相邻递增子数组 Ⅰ、检测相邻递增子数组 Ⅱ、好子序列的元素之和、统计小于 N 的 K 可约简整数
  • SQL Server 查看数据库表使用空间
  • 【机器学习案列】学生抑郁可视化及预测分析
  • SQL中的行转列,列转行
  • 一些常见的Java面试题及其答案
  • 网络攻击行为可视化分析系统【数据分析 + 可视化】
  • CSS | 实现三列布局(两边边定宽 中间自适应,自适应成比)
  • HTML文章翻页功能
  • 【已解决】【记录】2AI大模型web UI使用tips 本地
  • 阿里云直播Web
  • MTK6768 Android13 亮度条均匀调节实现
  • 一套UI精美、控件丰富、多主题的WinForm开源界面库
  • 【Uniapp-Vue3】pages设置页面路径及窗口表现
  • 寒假规划(服创比赛)
  • Nginx 访问状态统计功能配置与使用方法(status)
  • 【Docker】Docker与Docker compose离线安装
  • 宜自动化处理的五件事
  • PyTorch 时间序列与信号处理全解析:从预测到生成
  • 力扣 子集
  • uni-app h5修改浏览器导航栏的 title以及icon
  • 近红外数据预处理和简单分析matlab
  • 3、Go中的注释
  • 隐私计算,构建安全的未来数据空间