1. 程式人生 > >【JavaWeb開發】初步實現網站應用釘釘掃碼登入

【JavaWeb開發】初步實現網站應用釘釘掃碼登入

寫在前面:如果你還不知道釘釘是什麼,就趕緊問問Google。當然,這篇部落格是用流水線的形式完成釘釘掃碼登入。

第一步,看官方文件

如果你想要通過使用者掃碼獲取到他的個人資訊,那麼你需要完成全部的互動,如果你只是想為你的網站做一個免登入處理,其實只要拿到使用者的openid就可以了。當然我會在這篇部落格中貼出全部步驟的程式碼。

第二步,獲取appId和appSecret

  • 在左側的五個選單中點選自助工具,然後在右側的選單中建立掃碼登入應用授權,然後依次輸入名稱描述授權頁面logo地址(這個圖片最後會出現在使用者掃碼裝置中,建議使用壓縮圖片減少使用者載入時間)、回撥域名
    (一般都是寫一個子域名,比如),儲存之後便可以看到對應的appId以及appSecret了。

第三步,建立一個使用者掃碼介面並獲取臨時code

官網一共給大家提供了兩種方式,第一種就是直接跳轉到釘釘的二維碼掃描;第二種是嵌入到自己的網頁顯示二維碼。

因為我用的是第一種,並且這篇部落格也僅僅是建立在初步實現,所以這裡就不為大家介紹第二種嵌入方式了。

  • 獲取臨時code和引數state,首先再看一次官網說明文件:
    這裡寫圖片描述
    所以你在REDIRECT_URI跳轉回去的方法中,需要獲取到code和state兩個引數。而關於state,引數其實就是你在之前拼接URL的時候中的STATE,這裡建議大家可以使用時間戳(當用戶訪問的時候,因為URL不同,所以瀏覽器會重新獲取,避免瀏覽器因快取而導致二維碼無法使用等問題);

程式碼:

  • 拼接URL:
    /**
     * 
     * 描述:後臺預設跳轉到二維碼登入介面
     * 開發人員:暴沸
     * 開發時間: 2017年2月23日 下午9:09:57
     * 聯絡方式:[email protected] 
     *
     * @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) { } }

第四步,獲取access_token

        //獲取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");

第五步,獲取持久授權碼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");

如果你自習看程式碼,在這一步中我們已經拿到了使用者在這個網頁應用中的唯一標識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");

勝利就在眼前了!

第七步,獲取使用者資訊

直接傳送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");

大功搞成!

當然,這篇部落格只是用流水線的方式去寫這個接入的過程,實際上應該對程式碼進行優化,比如access_token應該使用定時任務獲取,如果每次都在使用者掃碼的時候去獲取,會佔用大量資源。

相關推薦

JavaWeb開發初步實現網站應用登入

寫在前面:如果你還不知道釘釘是什麼,就趕緊問問Google。當然,這篇部落格是用流水線的形式完成釘釘掃碼登入。 第一步,看官方文件 如果你想要通過使用者掃碼獲取到他的個人資訊,那麼你需要完成全部的互動,如果你只是想為你的網站做一個免登入處理,其實

Android開發如何實現android和伺服器長連線呢?推送訊息的原理

GGSN(Gateway GPRS Support Node 閘道器GPRS支援結點)模組就實現了NAT功能。因為大部分移動無線網路運營商都是為了減少閘道器的NAT對映表的負荷,所以如果發現鏈路中有一段時間沒有資料通訊時,會刪除其對應表,造成鏈路中斷。(關於NAT的作用及其原理可以檢視我的另一篇博文:關於使用

Android開發如何實現android和伺服器長連線呢?

GGSN(Gateway GPRS Support Node 閘道器GPRS支援結點)模組就實現了NAT功能。因為大部分移動無線網路運營商都是為了減少閘道器的NAT對映表的負荷,所以如果發現鏈路中有一段時間沒有資料通訊時,會刪除其對應表,造成鏈路中斷。(關於NAT的作用及其原理可以檢視我的另一篇博文:關於使用

外掛分享如何實現EmPireCMS帝國系統簡訊驗證功能

找到了一家不錯的簡訊外掛,有需要對接的可以檢視學習,在這邊分享一下,有需要的可以詳細看看,瞭解一下。http://www.ihuyi.com/ 外掛說明 本外掛系互億無線針對EmpireCMS v7.2 utf-8版本開發,外掛內的所有檔案均為對原檔案的修改,如果你的系統經過二次開發,安裝本外掛之前,請仔

利用長輪詢實現微信網頁版登入

掃碼登入操作過程 手機登入微信,利用“掃一掃”功能掃描網頁上的二維碼手機掃描成功後,提示“登入網頁版微信”;網頁上顯示“成功掃描 請在手機點選確認以登入”手機端點選“登入網頁版微信”,網頁跳轉到使用者的微信操作介面 整個掃碼登入的操作過程還是挺簡單的,而且互動地實時性比較

javawebBootStrap實現網站首頁

運用BootStrap框架對最開始的網站首頁進行一個重寫。 效果如下:  原始碼如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>

Android基於XMPP Smack Openfire開發IM初步實現兩個客戶端通訊

本部落格要介紹的內容: Openfire做伺服器端,兩個客戶端:Spark、android模擬器。實現兩個客戶端之間的通訊。 第一步:啟動openfire伺服器。(這裡需要用到兩個使用者登入,前面的部落格中已經說明如何新增使用者了。) [img] [/img] 第

Web開發Mean web開發 01-Express實現MVC模式開發

http scripts send javascrip 模板引擎 指令 開發環境 depend filter 簡介 Mean是JavaScript的全棧開發框架。更多介紹 用Express實現MVC模式開發是Mean Web全棧開發中的一部分。 Express 是一個基於

原始碼分享java實現對接簡訊驗證應用功能

今天公司提出一個需求,要在現有專案上收集註冊使用者的真實手機號,由於之前沒有接觸過這一塊,只能尋求度孃的幫助,經過一天的努力,終於完成了,現整理記錄下已備查閱。 1 解決方案:在註冊時要求使用者進行手機驗證。2 尋找簡訊供應商:由於對這一塊不是太懂,大學同學推薦一家他們公司在用的給我。3 程式碼實現 首先到

遊戲開發遊戲視窗實現自定義貼圖

//Windows視窗標頭檔案 #include <windows.h> //PlaySound函式包含的標頭檔案 #pragma comment(lib,"winmm.lib") //視窗寬度 #define WINDOW_WIDTH 1132 //視窗高度 #define

遊戲開發實現簡單對話方塊及音樂播放

//Windows視窗標頭檔案 #include <Windows.h> //PlaySound函式包含的標頭檔案 #pragma comment(lib,"winmm.lib") //主函式 int WINAPI WinMain(HINSTANCE hInstance,HINSTA

Python web 開發viewset 實現商品詳情頁的介面

我們如何來完成商品詳情頁的介面呢? 首先要配置一個商品詳情的url 按照我們正常的介面配法 ,應該是後面要加一個id 的,為什麼這裡沒有加id 呢? ,應該是rooter  register 的作用吧,等我在學習一遍基礎再來回答? 那麼我們再來寫viewset Mixin.Retriev

Android應用開發-(9)應用程式安裝解除安裝原理

本文粗體部分來自網路上的一篇文章,已不知出處,知道的告知,在此謝謝原作者。引出安裝解除安裝的原理之前,先實現一個簡單的安裝解除安裝應用程式的功能。文章是我之前寫的一篇部落格,這裡就不在敘述,只補充幾點: 1、由於程式碼中用到了PackageInstallObserver,PackageInstallObse

mahout筆記初步理解userCF(基於使用者的推薦演算法)在mahout的實現

昨天嘗試在java中搭建了一個mahout的小demo,實現的就是基於使用者的推薦演算法。程式碼如下(更多程式碼和測試資料庫)參見前一篇: public class RecommendTest { final static int NEIGHBORHOOD_NUM =

模組開發商品購物車的實現——3.使用者新增刪除商品的操作(控制層)

1.主頁面實現新增  首先在我們的主頁面相關的按鈕上加上連線地址的跳轉,轉到一個jsp頁面,這個jsp頁面實現的是新增商品的功能。index,jsp中需要加入的程式碼,例如:<!-- 在這裡將商品加入購物車 --><a href="addGood.jsp?i

嵌入式開發自定義AT指令實現sniffer網路嗅探功能

基礎 該功能是在NON-OS SDK下實現的。 Non-OS SDK 是不不基於作業系統的 SDK,提供 IOT_Demo 和 AT 的編譯。Non-OS SDK 主要使⽤用定時器和回撥函式的方式實現各個功能事件的巢狀,達到特定條件下觸發特定功能函式的目

模組開發商品購物車的實現——1.功能分析和效果演示

1.工程說明  前面在學習jsp中cookie內容的時候,我們寫了一個demo:商品瀏覽記錄功能的實現。現在,我們將在前面的那個工程上進行優化開發(主要是懶)。  回顧一下前面的那個工程實現了那些功能:商品資訊顯示頁面,單個商品資訊詳情頁面,近五條瀏覽商品記錄的頁面。  那麼

視訊開發Live555live555實現h264流RTSP傳輸

1.概述 liveMedia 庫中有一系列類,基類是Medium,這些類針對不同的流媒體型別和編碼。 其中的StreamFrame類檔案(如MPEG4VideoStreamFramer)為流傳輸關鍵。 2 重要概念: StreamFrame類:該類繼承Framed

JNI開發C++呼叫java函式的實現方法

本文的主要內容:C++中呼叫java類的成員函式和靜態成員函式 1,java程式碼 public class SNaviEngineManager { public void sendMe

Python開發C和Python之間的介面實現

## 更新:關於ctypes,見拙作 聊聊Python ctypes 模組 - 蛇之魅惑 - 知乎專欄 屬於混合程式設計的問題。較全面的介紹一下,不僅限於題主提出的問題。 以下討論中,Python指它的標準實現,即CPython(雖然不是很嚴格) 本文分4個部分C/C++ 呼叫 Python (基礎篇)—