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

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

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的博文对于技术这块都喜欢力求细致,通俗易懂,能达到上手即看效果,下手即能用的程度。

        

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流情

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值