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就折騰三四天,而且當時許可權驗證這一塊,具體實現流程不清楚。於是,就一直拖著。
最近有功夫,再把官方文件消化了一遍。終於有了頭緒。不得不說,官方文件是學習的第一手資料啊。
參考資料: