web项目对接钉钉扫码登录

2,912 阅读5分钟

写在前面

今天我们记录一下关于vue进行web开发的过程中对接钉钉的H5微应用的时候扫码登录的功能,你说他难吧,其实不难,很简单,你说他简单吧,看文档可能真的有点乱,不然您也不会来看我的帖子,我也看了别的大佬们写的关于这个的记录,不是说写的有问题,只是说很少有人站在别人开发的角度看待问题,导致很多人觉得还是不明白,所以今天就我写的过程中出现的问题进行描述一下大家可能迷茫的地方,尽量让每个开发者都看得懂!
感谢以下提供支持的博主:
填了个大空
易-水寒

官方文档地址

官方地址

  • 官方呢提供了两种实现的思路,也是不同的形式,具体使用哪一种呢,你们自己视情况而定

方案一

  • 方案一呢是不需要我们进行写二维码的实现过程的,这里直接使用官方的一个链接,也就是这个链接
https://oapi.dingtalk.com/connect/qrconnect?appid=APPID&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=REDIRECT_URI
redirect_uri
  • 这个链接两个点需要注意,第一个是redirect_uri参数,是通过后台配置的,具体什么位置配置的呢?看截图:
  • 回调地址
    这个需要你们的管理员进去,然后按照图示找到配置的地方,这里有人就问了,这个地址写什么?一般的话写的是您的web的登录入口的地址,比如说我的是https://csdn.clearlove/#login,那么你们就写自己的登录地址就好了。
appid
  • 这个参数同上,只要点击了创建扫码登录应用授权以后这个会自动生成的。

有了以上两个参数,就基本ok了,很多博主也是写到这里就不写了,所以很多人就迷茫了,这也不行啊,怎么登录的啊,下面的步骤是登录的部分,如果您使用了方案一,会发现点击扫码登录的时候会直接跳到一个新的页面,然后生成一个二维码,就像这样:
类似这样的二维码
有人说这个二维码怎么跳转过来的,很简单,就一个href,写一个span或者按钮的东西,事件绑定到下面的这个函数,点击执行函数就可以了,代码如下:

//扫码登录
            sweep_code() {
                window.location.href = "https://oapi.dingtalk.com/connect/qrconnect?appid=*******************&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=https://csdn.clearlove/#/login"
            }
  • 然后我们需要做的就是扫码,扫码之后会发现,他会回调到你地址上的redirect_uri这个参数的值的地址,也就是login的页面,这个时候我们需要做的就是将回调地址里面的code和state获取到,怎么获取呢?
    如图:
    回调url
    -我们使用下面的代码进行获取url中的code 和state
/**
 * @aim get code from url
 * @author clearlove
 * @data 19-09
 */
export default {
    getUrlKey:function(name){
        return decodeURIComponent((new RegExp('[?|&]'+name+'='+'([^&;]+?)(&|#|;|$)').exec(location.href)||[,""])[1].replace(/\+/g,'%20'))||null;
    }
}
  • 将这段js放到您的工具分类中,然后在login页面导入(您直接写到login页面也可以,只是这个js偏工具类,所以个人建议单独拿出来比较好,如果您是直接写到login的话,就不要写export了,直接当作一个函数使用就好了,真的是为你们操碎了心),然后直接使用getUrlKey方法进行获取code,我们在我们的login.vue文件(你的登录页面也就是你的回调地址指向的页面)在created的生命周期中进行如下代码操作,具体代码如下:
this.code = this.$utils.getUrlKey('code') //这个是用来给后端获取用户信息的
this.state = this.$utils.getUrlKey('state') //这个只是为了防止攻击的, 没有这个参数也可以,看后端要不要这个参数了,具体情况来定
  • 下面就是将code作为参数给到后端,他返回登录信息给您,然后您判断成功以后进如系统就可以了,为了让你们明白,我简单的画一个流程:
    流程
    以上是第一种方案,我这么写估计都明白了,还不明白的话,就下面留言吧!

方案二

很多人迷茫的更多的是使用方案2进行实现的过程,那其实方案2和方案一的区别就是一个体验稍微好点,因为不用跳转页面了,就比如我做的这个:
扫码登录
这种的实现过程其实差不多的,下面分两种情况,第一种是使用vue2.0版本的,第二种是vue3.0版本的

vue2.0

直接在您的index.html中引入如下的代码

<script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>

然后在登录的页面进行二维码的生成,这里说一点,就是二维码的生成以后的操作和方案一是一摸一样的,所以方案二我写的时候就写到如何生成二维码,有了二维码以后 ,扫码、回调、获取code、根据code获取用户信息、登录这一系列就和方案一一模一样了,这也是为什么方案一写的那么详细的原因,废话不多话,引入上面的钉钉的js以后呢,接着在页面上找一块你需要生成二维码的div,比如这样:

<div style="height: 310px;background: #ffffff" id="ding-login" v-show="isShow === 'ding'"></div>
  • 这里说明一下,要不要这个v-show都可以,我是提供了账号登录和扫码登录的功能,所以我需要切换,用到了v-show,您如果只有扫码登录,就完全不用,明白吧!
    接着我们需要在页面上直接在methods中使用如下代码:
dingLogin() {
                    this.$nextTick(() => {
                        var obj = DDLogin({
                            id: "ding-login",
                            goto: this.http_url,
                            style: "border:none;background-color:#FFFFFF;",
                            width: "300", // 二维码的宽度
                            height: "300" // 二维码的高度
                        })
                        // 重置扫码登录框的样式,让登录框居中
                        let box = document.getElementById('ding-login')
                        box.querySelector('iframe').style.top = '0'
                        box.querySelector('iframe').style.bottom = '0'
                        box.querySelector('iframe').style.left = '0'
                        box.querySelector('iframe').style.right = '0'
                        box.querySelector('iframe').style.margin = 'auto'
                    })
            },

说明:dingLogin这个函数就是点击扫码登录的时候调用的函数

  • 然后我们在created里实现如下代码:
scansettings().then(res => {
                this.appid = res.data.appkey
                this.appSecret = res.data.appsecret
                this.redirect_uri = res.data.redirect_uri
                this.redirects = encodeURIComponent(this.redirect_uri)
                this.http_url = encodeURIComponent("https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=" + this.appid + "&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=" + this.redirects + "")
                // 获取到扫码结果,并且跳转获取临时登录码
                var handleMessage = function (event) {
                    var origin = event.origin;
                    if (origin == "https://login.dingtalk.com") {
                        var loginTmpCode = event.data;
                        let url = "https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=" + this.appid + "&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=" + this.http_url + "&loginTmpCode=" + loginTmpCode + ""
                        location.href = url
                    } else {
                        console.info(event)
                    }
                };
                if (typeof window.addEventListener != 'undefined') {
                    window.addEventListener('message', handleMessage, false);
                } else if (typeof window.attachEvent != 'undefined') {
                    window.attachEvent('onmessage', handleMessage);
                }
            }).catch(err => {
                console.error(err)
            })

这里很多人看完以后就迷茫了,我简单的解释一下,官方给的源代码是这样的,官方源代码,区别在哪呢?其实就是参数获取的问题,因为这里我的appid和appSecret和回调的地址redirect_uri都是后端接口((scansettings)返回的,所以我页面加载的时候就直接请求接口,进行参数的获取,这里如果您这三个参数都是您自己写死的,那么您完全可以直接使用官方的代码,不过要加一行,也就是 location.href = url这点代码,不然没办法回调回来,官方说的原话是“获取到loginTmpCode后就可以在这里构造跳转链接进行跳转了”,具体怎么跳转,就是这点代码,然后你会发现二维码扫码以后就可以直接回调了,然后和方案一就一样了,这里还有一个点需要注意,就是回调的地址需要encodeURIComponent进行转码,这步是为了解决浏览器对特殊参数强制转码导致的url错乱的问题。

vue3.0

  • 如果您使用的是vue3.0的版本,会发现有的时候index.html这个文件没有了,怎么办呢?那2.0和3.0的代码写法是一样,区别在于怎么引入钉钉的js的问题,这里直接在export中引入如下代码:
components: {
            'dingtalk': {
                render(createElement) {
                    return createElement(
                        'script',
                        {
                            attrs: {
                                type: 'text/javascript',
                                src: 'https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js',
                            },
                        },
                    );
                },
            },
        },
  • 然后我们在页面上直接使用
   <dingtalk></dingtalk>

这样就引入了 ,下面的写法就和2.0一样了!

不用vue怎么实现钉钉扫码登录呢?

这个就比较简单了,上面的函数一样的写,区别在于vue存在生命周期,所以我们可以在created中实现code的获取,那一般的web项目我们只需要写到windows.onload的时候就可以了,有人就觉得,那么如果是两种方式(账号登录和扫码登录)都支持的话,是不是每次进来的时候就会报错呢?提示什么code不存在什么的,这个问题很好解决,只要我们获取code之前if判断一下code是不是存在,不存在再进行code的获取就好了!

如果对这个扫码登录还有什么问题的话,可以留言,我看到的会及时回复的,我追求的是博客不写就不写了,既然写了,就追求每个开发者都看得懂!