1. 程式人生 > >javaweb實戰 微信網頁授權——基於測試號開發

javaweb實戰 微信網頁授權——基於測試號開發

(一)開發背景

       一般的網站登入驗證這一塊的開發,都是使用自己獨立的一套的賬號體系。問題是顯然易見的:使用者在每一個網站都要到註冊一個新的賬戶密碼。使用者就需要耗費腦力眾多的網站密碼。很多時候,並不是使用者密碼被盜,而是使用者自己忘記了密碼。

       這樣,微信授權登入的優勢就體現出來了。這年代,還有誰不用微信的嗎?使用者只需要掃碼即可登入,帶來的便捷性不言而喻。

(二)效果演示

      專案原始碼: 

(三)原理分析

 官方文件是第一手資料,也是最好的資料。文件開篇即說明:如果使用者在微信客戶端中訪問第三方網頁,公眾號可以通過微信網頁授權機制,來獲取使用者基本資訊,進而實現業務邏輯。但,這裡就有一個問題了。必須是微信客戶端直接訪問網頁,才能獲取使用者資訊。那怎麼實現使用者pc端網頁的授權登入呢?(這裡說的有點含糊,但這個問題確是關鍵!)

    解決思路:pc端網站直接生成二位碼,引發使用者授權登入。微信客戶端確認授權後,會帶code引數一起回撥開發者自定義的地址。開發者獲取到code(已經成功了一半)後,利用code值來呼叫一系列的介面,即可獲取到使用者的基本資訊:包括openid,nickname,headimgurl.....

(四)開發準備

    (1)  申請測試號:

   成功的話,應該能看到這頁面

  

    (2)配置回撥域名

         a.

          

         b.這裡提一下:測試號支援內網ip,比如:192.168.2.123:8080。填寫地址的必須是微信客戶端能訪問的。

        

(五)開發

      (1)專案技術棧

       a. java web: 使用原生的servlet + jsp

       b. 資料庫: mysql + c3p0連線池

       c. jwt 生成token

       d. HttpSevletResponse操作Cookie

      (2)專案初始化

       專案追求純粹化,不適用任何框架。c3p0連線池也是自定義的java類。

       可根據個人需求,升級為ssh,ssm均可。

         (3)引導使用者同意授權,獲取code

         根據官方文件,使用者必須在微信客戶端訪問連結,才有機會獲取code。所以我們要引導使用者訪問某個連結。

          pc端與微信客戶端最便捷的互動方式就是二維碼。所以,在前端,我們需要生成二維碼的js庫。這裡,我選擇“jquery.qrcode.min.js”,一個非常輕量級的庫。關鍵程式碼:

                

         使用者同意授權後,就會跳轉到redirect_uri: http://vps.wiwikiky.top:8080/front/weixin/auth。我們就需要設定對應的控制器來的攔截這個請求了。

        

        可以看到,我們可以拿到微信回撥的code,以及我們自定義的uuid引數。微信回撥,是比較關鍵的一步,也是比較困難的非同步。如果你能成功攔截到微信回撥的請求並且獲取到code引數,那你就成功了一半了。

      (4)通過code換取access token,通過access token 拉取資訊

       到了這裡,我們只需要根據官方文件所指引的步驟,調取相對應的api即可。

      在專案裡,我對調取api進行了封裝。

    

          只需要替換成自己對應APPID,SECRET即可。具體的呼叫以及業務判斷,可參照我的原始碼。以拿到使用者資訊為成功標準:openid,等等。

      (5)更新使用者資訊或新增

拿到openid(使用者唯一標識)後,證明微信客戶端授權成功。到了這裡,我們可以根據自己專案需求進行對應了。無論基於session驗證,還是基於token驗證,都是可以的。這裡我選擇token的驗證方式:使用jwt生成token,並存放瀏覽器的cookie中。每次訪問時,都進行token驗證。

       具體步驟:獲取到openid後,根據openid來對使用者表進行查詢。如果使用者存在,則更新hash,生成token;如果使用者不存在,這插入使用者資訊。這裡,吃瓜群眾可能會對hash值有疑問了,hash值有什麼作用?這裡的hash值就是保證使用者單點登入。舉個例子,如果使用者使用chrome瀏覽器登入後,再使用360瀏覽器登入,那麼Chrome瀏覽的token就非法了。相當於chrome瀏覽器被迫下線的效果。

      這裡可以展示下使用者表:

     

     (6)token的生成與解析

初學者剛學習jwt(java web token)時,會感覺jwt非常高大上,以及無從下手。但是java中有相對的包,使用非常方便。

     直接上程式碼:

       說白一點:token就是帶有資訊、加密過的字串。因為我們使用了私鑰,除非別人知道了祕鑰,否則無法破解。token能加密,也可解密。解密後,我們就可取回相對的資訊了

      我們可以看到:可以把我們的需要儲存的資訊封裝到Map物件,再生成token; 也可以解析token得到我們的想要的資訊。

     

     在這裡,我們只封裝openid,hash,timestamp。

    各自的作用: 

        openid:驗證使用者身份;

        hash: 單點登入;

        timestamp: 設定token的有效期

     (7)使用Filter過濾器進行許可權認證

      具體步驟:

        攔截/admin/*路線下的所有請求,取出cookie中token。

        若token不存在,不放行,重定向到登入頁面。

        若token存在,分別對openid,hash,timestamp進行校驗,都合法,則放行;否則,重定向到登入頁面。

        另外,我們還可以取出請求路徑,作為引數附帶到登入頁面。但登入成功後,可直接跳轉到原來頁面。

    (六)難點突破

我們先用流程圖來回顧整個授權過程。

       這裡的難點就是:微信授權後,伺服器怎麼通知pc客戶端?

       這裡的解決方案是:使用ajax輪詢。pc生成二維碼前,隨機生成一個uuid,作為該視窗的臨時標識。授權後,伺服器根據uuid找到對應的視窗。具體實現,如下:

      (1)請求生成時,就生成一個唯一標識,並存儲在全域性變數中

        (2)前臺生成二維碼時,附帶上該引數

      (3)微信後調後,再取出改引數。確認是哪個視窗的驗證。

     (4)授權後,打上對應uuid成功授權的標識

     (5)ajax輪詢中,根據uuid,找到uuid是否授權的標識

       js程式碼:

      至此,微信網頁授權大功告成。具體請參考原始碼。

  (七)注意:

      原始碼執行需要修改的地方:

       a. 初始化使用者表,原始碼中有相對的sql;修改db.properties檔案,對應username,password

       b. WeixinAuthUtils.java 修改成自己的APPID,SECRET

       c. weixinlogin.jsp檔案中生成二維碼對應的欄位改為自己定義的回撥地址(與配置回撥域名相對應上)。

  (八)總結

想做微信授權登入已經很久了,最開始是看到慕課網中spring boot開發餓了麼專案時做的這個功能,但人家用的是正式號來做的,省了很多功夫。後來聽說測試號也可以做,自己就看著網上的部落格,跟官方文件來做。結果,獲取code就折騰三四天,而且當時許可權驗證這一塊,具體實現流程不清楚。於是,就一直拖著。

      最近有功夫,再把官方文件消化了一遍。終於有了頭緒。不得不說,官方文件是學習的第一手資料啊。

參考資料: