zoukankan      html  css  js  c++  java
  • 【JavaWeb开发】初步实现网站应用钉钉扫码登录

    目录(?)[+]

    写在前面:如果你还不知道钉钉是什么,就赶紧问问Google。当然,这篇博客是用流水线的形式完成钉钉扫码登录。

    第一步,看官方文档

    网站应用钉钉扫码登录开发指南(钉钉官网)

    如果你想要通过用户扫码获取到他的个人信息,那么你需要完成全部的交互,如果你只是想为你的网站做一个免登录处理,其实只要拿到用户的openid就可以了。当然我会在这篇博客中贴出全部步骤的代码。

    第二步,获取appId和appSecret

    • 登录/注册到钉钉开发者官网:新版开发者平台:http://open-dev.dingtalk.com
    • 在左侧的五个菜单中点击自助工具,然后在右侧的菜单中创建扫码登录应用授权,然后依次输入名称描述授权页面logo地址(这个图片最后会出现在用户扫码设备中,建议使用压缩图片减少用户加载时间)、回调域名(一般都是写一个子域名,比如http://oa.dingtalk.com),保存之后便可以看到对应的appId以及appSecret了。

    第三步,创建一个用户扫码界面并获取临时code

    官网一共给大家提供了两种方式,第一种就是直接跳转到钉钉的二维码扫描;第二种是嵌入到自己的网页显示二维码。

    因为我用的是第一种,并且这篇博客也仅仅是建立在初步实现,所以这里就不为大家介绍第二种嵌入方式了。

    https://oapi.dingtalk.com/connect/qrconnect?appid=APPID&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=REDIRECT_URI

    将自己的appid填写在APPID处,将自己希望扫码后跳转到的地址填写在REDIRECT_URI,比如可以填写为http://google.com/dingtalkLogin或者http://google.com/dingtalkLogin.action等等,大家可以根据自己的实际情况填写。

    • 获取临时code和参数state,首先再看一次官网说明文档:
      这里写图片描述
      所以你在REDIRECT_URI跳转回去的方法中,需要获取到code和state两个参数。而关于state,参数其实就是你在之前拼接URL的时候中的STATE,这里建议大家可以使用时间戳(当用户访问的时候,因为URL不同,所以浏览器会重新获取,避免浏览器因缓存而导致二维码无法使用等问题);

    代码:

    • 拼接URL:
        /**
         * 
         * 描述:后台默认跳转到二维码登录界面
         * 开发人员:暴沸
         * 开发时间: 2017年2月23日 下午9:09:57
         * 联系方式:admin@baofeidyz.com 
         *
         * @param request
         */
        @RequestMapping(value="login")
        public void toALiDingDing(HttpServletResponse response){
            //这是我自己写的一个获取时间戳的Util,前期大家可以不管这个STATE
            TimeUtil timeUtil = new TimeUtil();
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("https://oapi.dingtalk.com/connect/qrconnect?appid=APPID&")
                .append("response_type=code&scope=snsapi_login&state=")
                .append(timeUtil.getNow())
                .append("&redirect_uri=")
                .append("REDIRECT_URI");
            try {
                response.sendRedirect(stringBuilder.toString());
            } catch (IOException e1) {
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    第四步,获取access_token

    关于Java如何封装get和post请求可以参考一下我自己写的博客:
    【JavaWeb开发】用Apache的HttpClient4.5完成HttpGet请求
    【JavaWeb开发】用Apache的HttpClient4.5完成HttpPost请求

            //获取accesstoken
            HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
            HttpClient httpClient = httpClientBuilder.build();
            HttpResponse httpResponse = null;
            String url = "https://oapi.dingtalk.com/sns/gettoken?appid=APPID&appsecret=APPSECRET";
            HttpGet httpGet = new HttpGet(url);
            try {
                httpResponse = httpClient.execute(httpGet);
            } catch (Exception e) {
            }
            BufferedReader bufferedReader = null;
            StringBuilder entityStringBuilder=new StringBuilder();  
            //得到httpResponse的状态响应码  
            int statusCode=httpResponse.getStatusLine().getStatusCode();  
            if (statusCode==HttpStatus.SC_OK) {  
                //得到httpResponse的实体数据  
                HttpEntity httpEntity=httpResponse.getEntity();  
                if (httpEntity!=null) {  
                    try {  
                        bufferedReader=new BufferedReader  
                        (new InputStreamReader(httpEntity.getContent(), "UTF-8"), 8*1024);  
                        String line=null;  
                        while ((line=bufferedReader.readLine())!=null) {  
                            entityStringBuilder.append(line+"/n");  
                        }  
                    } catch (Exception e) {  
                    }  
                }  
            }
            JSONObject jsonObject = new JSONObject(entityStringBuilder.toString());
            String access_token = jsonObject.getString("access_token");
    • 1
    • 2

    第五步,获取持久授权码persistent_code

    获取用户授权的持久授权码(钉钉官网)

    在官网文档中指出,需要使用之前获取到的临时code以及access_token两个参数来发送一个POST请求:

            //获取用户授权的持久授权码
            String url3 = "https://oapi.dingtalk.com/sns/get_persistent_code?access_token="+access_token;
            System.out.println("url3="+url3);
            HttpPost httpPost3 = new HttpPost(url3);
            //封装临时授权码
    
            JSONObject jsonObject3_1 = new JSONObject();
            jsonObject3_1.put("tmp_auth_code", code); 
            HttpEntity httpEntity3 = null;
            httpEntity3 = new StringEntity(jsonObject3_1.toString(),"UTF-8");
            httpPost3.setEntity(httpEntity3);
            HttpResponse httpResponse3 = null;
            try {
                httpResponse3 = httpClient.execute(httpPost3);
            } catch (Exception e) {
                // TODO: handle exception
            }
            StringBuilder entityStringBuilder3=new StringBuilder();
            //得到httpResponse的状态响应码  
            int statusCode3=httpResponse3.getStatusLine().getStatusCode();  
            if (statusCode3==HttpStatus.SC_OK) {  
                //得到httpResponse的实体数据  
                HttpEntity httpEntity3_2=httpResponse3.getEntity();  
                if (httpEntity3!=null) {  
                    try {  
                        bufferedReader=new BufferedReader  
                        (new InputStreamReader(httpEntity3_2.getContent(), "UTF-8"), 8*1024);  
                        String line=null;  
                        while ((line=bufferedReader.readLine())!=null) {  
                            entityStringBuilder3.append(line+"/n");  
                        }  
                    } catch (Exception e) {  
                        e.printStackTrace();  
                    }  
                }  
            }
            JSONObject jsonObject3_2 = new JSONObject(entityStringBuilder3.toString());
            String persistent_code = jsonObject3_2.getString("persistent_code");
            String openid = jsonObject3_2.getString("openid");
    • 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

    如果你自习看代码,在这一步中我们已经拿到了用户在这个网页应用中的唯一标识openid了,其实到这里就可以实现网站的免登录扫码了哦!

    第六步,获取SNS_TOKEN

    获取用户授权的SNS_TOKEN(钉钉官网)

    文档指出,我们需要在POST请求中封装之前获取到的access_token、openid以及persistent_code

            //获取用户授权的SNS_TOKEN
            String url4 = "https://oapi.dingtalk.com/sns/get_sns_token?access_token="+access_token;
            HttpPost httpPost4 = new HttpPost(url4);
            JSONObject jsonObject4 = new JSONObject();
            jsonObject4.put("openid", openid);
            jsonObject4.put("persistent_code", persistent_code);
            HttpEntity httpEntity4 = null;
            httpEntity4 = new StringEntity(jsonObject4.toString(),"UTF-8");
            httpPost4.setEntity(httpEntity4);
            HttpResponse httpResponse4 = null;
            //重新获取一个新的httpClient
            HttpClientBuilder httpClientBuilder2 = HttpClientBuilder.create();
            HttpClient httpClient2 = httpClientBuilder2.build();
            try {
                httpResponse4 = httpClient2.execute(httpPost4);
            } catch (Exception e) {
                // TODO: handle exception
            }
            StringBuilder entityStringBuilder4=new StringBuilder();
            //得到httpResponse的状态响应码  
            int statusCode4=httpResponse4.getStatusLine().getStatusCode();  
            if (statusCode4==HttpStatus.SC_OK) {  
                //得到httpResponse的实体数据  
                HttpEntity httpEntity4_1=httpResponse4.getEntity();  
                if (httpEntity4_1!=null) {  
                    try {  
                        bufferedReader=new BufferedReader  
                        (new InputStreamReader(httpEntity4_1.getContent(), "UTF-8"), 8*1024);  
                        String line=null;  
                        while ((line=bufferedReader.readLine())!=null) {  
                            entityStringBuilder4.append(line+"/n");  
                        }  
                    } catch (Exception e) {  
                        e.printStackTrace();  
                    }  
                }  
            }
            //
            JSONObject jsonObject4_1 = new JSONObject(entityStringBuilder4.toString());
            String sns_token = jsonObject4_1.getString("sns_token");
    • 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

    胜利就在眼前了!

    第七步,获取用户信息

    获取用户授权的个人信息(钉钉官网)

    直接发送GET请求即可!

            //获取用户授权的个人信息
            String url5 = "https://oapi.dingtalk.com/sns/getuserinfo?sns_token="+sns_token;
            HttpGet httpGet5 = new HttpGet(url5);
            HttpResponse httpResponse5 = null;
            try {
                HttpClient httpClient3 = httpClientBuilder.build();
                httpResponse5 = httpClient3.execute(httpGet5);
            } catch (Exception e) {
                // TODO: handle exception
            }
            StringBuilder entityStringBuilder5=new StringBuilder();
            //得到httpResponse的状态响应码  
            int statusCode5=httpResponse5.getStatusLine().getStatusCode();  
            if (statusCode5==HttpStatus.SC_OK) {  
                //得到httpResponse的实体数据  
                HttpEntity httpEntity5=httpResponse5.getEntity();  
                if (httpEntity5!=null) {  
                    try {  
                        bufferedReader=new BufferedReader  
                        (new InputStreamReader(httpEntity5.getContent(), "UTF-8"), 8*1024);  
                        String line=null;  
                        while ((line=bufferedReader.readLine())!=null) {  
                            entityStringBuilder5.append(line+"/n");  
                        }  
                    } catch (Exception e) {  
                        e.printStackTrace();  
                    }  
                }  
            }
            JSONObject jsonObject5_1 = new JSONObject(entityStringBuilder5.toString());
            JSONObject jsonObject5 = jsonObject5_1.getJSONObject("user_info");
            String nick = jsonObject5.getString("nick");
            String unionid = jsonObject5.getString("unionid");
            String dingId = jsonObject5.getString("dingId");
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    大功搞成!

    当然,这篇博客只是用流水线的方式去写这个接入的过程,实际上应该对代码进行优化,比如access_token应该使用定时任务获取,如果每次都在用户扫码的时候去获取,会占用大量资源。

  • 相关阅读:
    Dubbo源码分析之ExtensionLoader加载过程解析
    大型网站系统与java中间件实践-阅读笔记
    多线程编程-设计模式之保护性暂挂(Guarded Suspesion)模式
    多线程编程-设计模式之不可变对象模式
    Spring技术内幕阅读笔记(一)
    mysql存储过程语法及实例
    Spring-boot官方案例分析之data-jpa
    Spring-boot官方案例分析之log4j
    Spring Boot应用的测试——Mockito
    linux系统安装redis
  • 原文地址:https://www.cnblogs.com/wdcwy/p/6933737.html
Copyright © 2011-2022 走看看