http://blog.csdn.net/baofeidyz/article/details/59059379
版權聲明:轉載請注明我的個人微信平台 暴沸
寫在前面:如果你還不知道釘釘是什么,就趕緊問問Google。當然,這篇博客是用流水線的形式完成釘釘掃碼登錄。
第一步,看官方文檔
如果你想要通過用戶掃碼獲取到他的個人信息,那么你需要完成全部的交互,如果你只是想為你的網站做一個免登錄處理,其實只要拿到用戶的openid就可以了。當然我會在這篇博客中貼出全部步驟的代碼。
第二步,獲取appId和appSecret
- 登錄/注冊到釘釘開發者官網:新版開發者平台:http://open-dev.dingtalk.com
- 在左側的五個菜單中點擊自助工具,然后在右側的菜單中創建掃碼登錄應用授權,然后依次輸入名稱、描述、授權頁面logo地址(這個圖片最后會出現在用戶掃碼設備中,建議使用壓縮圖片減少用戶加載時間)、回調域名(一般都是寫一個子域名,比如http://oa.dingtalk.com),保存之后便可以看到對應的appId以及appSecret了。
第三步,創建一個用戶掃碼界面並獲取臨時code
官網一共給大家提供了兩種方式,第一種就是直接跳轉到釘釘的二維碼掃描;第二種是嵌入到自己的網頁顯示二維碼。
因為我用的是第一種,並且這篇博客也僅僅是建立在初步實現,所以這里就不為大家介紹第二種嵌入方式了。
將自己的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
- 首先我們還是看一下官方說明文檔:
獲取釘釘開放應用的ACCESS_TOKEN(釘釘官網)
所以我們需要使用java代碼向釘釘服務器端發送一個GET請求
關於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
文檔指出,我們需要在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應該使用定時任務獲取,如果每次都在用戶掃碼的時候去獲取,會占用大量資源。