微信授權登入mock(在沒有真實微信賬號的情況下測試大量微信賬戶授權登入的情況)
場景介紹
對於構建在微信公眾號的系統,帳號體系往往使用微信授權登入(如各類微信商城應用系統)。
這樣操作不僅可以實現靜默註冊,對使用者幾乎是無感的,同時也達到了區分使用者,獲取使用者基本資訊(頭像,暱稱等)。
使用微信授權的模式可以說一次性替代使用者註冊及使用者登入。
也是基於上面優勢,我們平常也可以看到在微信公眾號上的應用有不少都是使用微信的這種授權登入( https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842 )
因為這種帳號體系是以微信帳號為主體的,平時我們如果要對該類系統進行測試,就必須使用到真實的微信帳號完成登入或註冊。
如果想要對登入或註冊曾經進行效能方面的測試那會比較棘手(因為我們可能沒有足夠的微訊號)
以下圖為例我們先分析這個註冊/登入流程
如圖上面的1,2,3步都是在微信APP裡完成的(與我們作為測試物件的應用伺服器未產生聯絡)
直到第4步驟微信瀏覽器才向我們的應用伺服器傳送了請求(該請求負責將前面步驟得到的code傳遞到我們自己的業務服務,該請求才是我們自己業務伺服器開始驗證登入的開始)
一般我們的伺服器得到code後,會在向微信服務請求使用者資訊,拿到使用者資訊後處理自己的業務邏輯(註冊或是登入)
所以能看出來,登入或測試的關鍵就是第4步這個介面。
我們在進行效能測試時,設計的登入或註冊邏輯(事務)主要就在於第4步請求測試資料的準備。
因為我們應用服務從第4步拿到code後會用此code向微信查詢使用者資訊,即這個code是微信即時生成的,我們是不可能提前拿到一批能用的code用來測試的。
現在如果為了測試可以選擇修改服務邏輯讓其接收虛擬code,對虛擬code進行特殊處理完成虛擬的註冊。但是這樣為了測試來改變遠工程的邏輯是十分不可取的,測試的物件應儘量與實際使用者使用到的維持一致,而且這裡的場景就是為了測試註冊或登入的效能,為了測試而故意改了一份針對測試的註冊或登入的邏輯顯然不合適。
我們進一步分析業務服務的邏輯,業務伺服器會拿獲得的code向微信換取使用者資訊
如上圖業務伺服器使用code向微信伺服器換來了openid 及 access_token等關鍵資訊 (第一幅圖是微信介面說明,第二副圖是應用伺服器向微信請求的一個例項)
這時其實拿到openid即可以確定使用者是新使用者還是老使用者,如果新使用者可以進行新建使用者的操作,如果是老使用者則可以進行使用者登入的邏輯。
當然現實中應用服務可能還會使用access_token去向微信拉取使用者頭像,暱稱等資訊(https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN),這取決於大家產品自己的業務。
如上所述不難發現,如果使用錯誤的code,微信服務一定會返回錯誤,導致註冊或登入業務中斷。現在我們要克服的就是,如何讓錯誤的code也能有正常的返回。介面是微信的,微信顯然不會做這種事情。那我們在不更改業務服務的任何邏輯的同時能不能在我們應用伺服器的網路層面上mock微信的這個介面,讓不被微信承認的code也能返回正常的資料。
答案是可以的,上面這個需求是可以通過FreeHttp來完成對。藉助FreeHttp可以截獲使用code換openid及access_token的請求,然後返回我們自己構建的測試資料給業務服務使用。(FreeHttp 的說明及安裝可以看這裡 https://www.cnblogs.com/lulianqi/p/10428551.html )
下面以一個實際微信登入場景為例說明如何使用FreeHttp完成微信認證
1:配置代理(Fiddler)
為了完成需求,我們首先要為業務伺服器配置HTTP代理到我們的Fiddler上。
一般我們的伺服器都是Linux,這裡我們以CentOS,應用容器Tomcat 為例說明代理配置過程
配置機器全域性代理很容易
修改 /etc/profile 檔案
新增上面的資訊即可
不過JVM可能不會使用系統HTTP代理,所以我們需要單獨配置Tomcat的代理
通過設定jvm的proxyhost來實現設定tomcat中引用程式的代理
在tomcat的配置檔案catalina.bat/sh中設定-Dhttp.proxySet=true -Dhttp.proxyHost=proxyserver -Dhttp.proxyPort=8888
配置示例如上圖在以上位置加上指定引數即可(不同應用容器或服務框架都有自己的代理設定方式,大家可以在網路上搜索到)
新增配置資訊後重啟tomcat即可(記得伺服器與代理服務所在網路上必須是能連通的)
還有一步新增fiddler證書到伺服器(為了能解析HTTPS請求)
如上圖在我們自己的電腦中匯出證書
在伺服器上進行如下操作
- 安裝 ca-certificates 包
yum install ca-certificates
- 啟用 dynamic CA configuration
update-ca-trust enable
- 新增證書到指定目錄 (fiddler證書)
cp FiddlerRoot.cer /etc/pki/ca-trust/source/anchors/
- 生效
update-ca-trust extract
以上步驟完成後可以測試一下Fiddler是否能獲取伺服器傳送的請求
觸發伺服器向外傳送請求,我們在Fiddler上應該能捕獲相應請求(上圖就是一個我們應用伺服器傳送給微信的https請求)
2:配置FreeHttp
FreeHttp作為第三方Fiddler擴充套件外掛需要單獨安裝,安裝方法十分簡單(安裝步驟見 https://www.cnblogs.com/lulianqi/p/10428551.html#_label0_1 )
按照我們前面的分析,實際應用伺服器是需要向微信傳送code(https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code)
應用伺服器需要根據返回資料再進處理一步業務邏輯
那我們現在直接篡改這條請求返回值,讓他對不合法code的請求也返回正常的返回資料
先新增一個引數化資料(用於使每次返回資料都不一樣)
如上圖,我們新增一個逐步遞增的openid引數資料(按圖標註1,2,3步驟新增即可,注意紅框部分選擇引數型別及引數的格式)
這個引數表示以0001開始每次取值逐步遞增(在類表處選取該引數,可以重置或設定該引數的值)
再新增一個用於產生合規響應的Response Replace規則
如上圖新增一個Response Replace規則
因為是替換響應不需要將真實發送到微信的伺服器這裡勾選Response Direct(同時為了模擬真實場景加上50ms的延時,反覆測試微信的這條介面響應時間都控制在50ms到100ms)
在圖最大編輯框中設定相應資料(正確響應資料應該是什麼格式,抓取一個正常的請求就可以得到),同時我們為返回json裡openid新增一個引數數化資料(實際就是TestOpenId加上一個遞增的ID,這個遞增ID就是前面設定的引數化資料,這裡為了方便演示,僅對openid進行說明,實際其他幾個返回項也是有意義的)
紅線處*#test_openid(+)*#即表示前面新增的使用者引數(因為使用到使用者引數,需要滑鼠右鍵在彈出框中把use Parameter Data 勾上)
設定完成後,點選右下角綠色確認按鈕新增規則
完成以上設定後,後注意在右側Response Rule列表處,設定啟用Response Rule,及勾選需要執行的規則(上圖紅框區域)
3:測試規則
前面最開始我們也分析過https://業務域名及路徑?code=061v6AGK1pOTj40nF0EK1LNwGK1v6AGV&state=輔助引數 (文中第一張圖的第4步,這個地址也是在前面第2步的回撥地址中設定的)
我們使用Fiddler的Composer構造這個請求(當然您可以通過其他測試工具甚至是瀏覽器構建請求進行除錯)
如上圖我們主要關注的code(我們這裡自己構造code,實際這個code不是一個真實的code)
點選Execute傳送測試請求
如上圖,可以看到伺服器發給微信的請求已經被我們替換掉了,而且返回我們設定的“合法資料”。(我們我應用伺服器這個時候會認為是openid為TestOpenId0001的使用者來登入或註冊了,然後會進入相應的業務)
通過資料庫驗證使用者是否成功建立成功(當然正常情況下按不同業務需求,註冊一個使用者還有許多資料需要驗證)
4:開始登入測試
對登入業務進行壓力測試,同樣可以使用很多工具,我這裡使用常用的JMeter進行演示
我們使用先使用JMeter依次傳送https://業務域名及路徑?code=TestOpenId0001&state= (使code逐步遞增,這裡遞增是為了防止應用服務有快取策略)
注意JMeter預設不使用系統代理,所以需要如上圖手動配置代理

這裡使用100個使用者同時登入(持續時間30秒,當然實際測試中有更加複雜的業務,持續時間跟使用者數也會更多)
通過對資料庫的檢查,我們基本上可以確認30秒裡這10個使用者建立了311個賬戶(而實際上我們並沒有使用311個微訊號)
簡單的測試我們應用服已經表現出效能瓶頸(平均響應達到了8秒)

同時新增伺服器監控,可以檢視測試中伺服器的壓力情況(上圖表面測試中應用執行緒數量明顯增多,JVM的GC也加快了,可以反覆嘗試增加壓力觀察是否存在瓶頸)
最後我們就可以根據自己的業務,新增更多的業務場景進行有針對性的測試。
上面只是一個例子,演示如何通過截獲伺服器與微信認證伺服器的請求,以達到測試自己業務微信認證登入的過程。
大家可以利用這個思路,結合自己的需求,進行有針對性的測試。