举杯邀月

vue 使用钉钉扫码登陆(附PHP后台代码)

摘要:vue 使用钉钉扫码登陆(附PHP后台代码),使用钉钉客户端扫码并确认登录您的web系统,在您的系统内获得正在访问用户的钉钉身份,而用户无需输入账户密码。

钉钉扫码登陆流程

1、通过 dingScanCodeLogin 获取登陆地址渲染二维码
2、扫码后获取 loginTmpCode ,通过 dingSnsAuthorize 获取授权地址
3、打开回调地址,钉钉将 code 及 state 参数回调到 dingCallback 方法,方法通过 state 参数的第三个参数,把用户信息通过加密进行回传

钉钉官方文档:https://ding-doc.dingtalk.com/doc#/serverapi2/kymkv6

vue 页面

<template>
    <div class="LoginBox">
        <div id="ding-login">div>
        <remote-js src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js">remote-js>
        <a ref="dingCallback" target="_blank" :href="dingCallbackUrl" style="display: none;">跳转a>
    div>
template>

<script>
    import { Base64 } from 'js-base64';
    export default {
        data (){
            return {
                dingCallbackUrl: ''
            }
        },
        created() {
            var _this = this;
            /** 获取到扫码结果,并且跳转获取临时登录码 **/
            var handleMessage = function (event) {
                var origin = event.origin;
                if (origin == "https://login.dingtalk.com") {
                    let domain = window.location.origin;
                    /** 将跳转地址base64加密传到后台 **/
                    let redirect = Base64.encode(domain+'/dingdingcallback');
                    /** 请求接口验证并获取钉钉扫码登陆结果,然后携带用户信息跳转到另一个页面上 **/
                    Api.DingSnsAuthorize({ loginTmpCode: event.data, redirect: redirect, domain: domain }).then(res=>{
                        _this.dingCallbackUrl = res.data.uri;
                        setTimeout(()=>{
                            _this.$refs.dingCallback.click();
                        }, 800);
                    });
                }
            };
            if (typeof window.addEventListener != 'undefined') {
                window.addEventListener('message', handleMessage, false);
            } else if (typeof window.attachEvent != 'undefined') {
                window.attachEvent('onmessage', handleMessage);
            }
            /** 获取顶顶扫码登陆参数,生成二维码 **/
            Api.dingScanCodeLogin().then(res=>{
                this.$nextTick(() => {
                    // eslint-disable-next-line no-undef
                    DDLogin({
                        id: "ding-login",
                        goto: encodeURIComponent(res.data.uri),
                        style: "border:none;background-color: rgba(0,0,0,0)",
                        width : "250",
                        height: "350"
                    })
                })
            });
        },
    }
script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

后台(PHP)代码

/**
     * @Desc   获取钉钉扫码登陆URl
     * @method GET
     * @return \Illuminate\Http\JsonResponse
     * @author yashuai
     * @Time 2020/6/10 14:24
     */
    public function dingScanCodeLogin(){
        $data = [
            'appid' => 【申请的appid】,
            'response_type' => 'code',
            'scope' => 'snsapi_login',
            'state' => 【自定义参数】,
            'redirect_uri' =>【配置的回调地址】
        ];
        
        $domain = 'https://oapi.dingtalk.com/connect/qrconnect?';
        return [
            'uri' => $domain.http_build_query($data)
        ];
    }
    
    /**
     * @Desc  获取钉钉扫码登陆授权回调地址
     * @method GET
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * @author yashuai
     * @Time 2020/6/17 15:37
     */
    public function dingSnsAuthorize(Request $request)
    {
        $loginTmpCode = $request->input('loginTmpCode');
        $redirect = $request->input('redirect');
        $domain = $request->input('domain');
        $config = config('const.ding_talk');
        $data = [
            'appid' => 【申请的appid】,
            'response_type' => 'code',
            'scope' => 'snsapi_login',
            'state' => 【自定义参数】,
            'redirect_uri' => 【配置的回调地址】,
            'loginTmpCode' => $loginTmpCode
        ];
        $domain = 'https://oapi.dingtalk.com/connect/oauth2/sns_authorize?';
        return [
            'uri' => $domain.http_build_query($data)
        ];
    }

    /**
     * @Desc   钉钉登陆回调地址
     *          钉钉扫码登陆具体流程查看readme.md
     * @method GET
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * @author yashuai
     * @Time 2020/6/10 14:39
     */
    public function dingCallback(Request $request)
    {
        $state = explode('_', $request->input('state'));
        $code = $request->input('code');
        $userInfo = ScanCodeLoginServices::instance()->dingCallback($code);
        $res = SignInServices::instance()->dingLogin($userInfo, $request->ip());
        header("Location:".base64_decode($state[2])."?code=".base64_encode(json_encode($res)));exit;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

以上代码只是样例,可以用但需要完善,方便书写所以没有封装。

作者:举杯邀月

出处: http://www.hug-code.cn/archives/5fdb1ee7a30aa.html

2020-10-18 标签: 三方授权登录vue