場景介紹
對於構建在微信公眾號的系統,帳號體系往往使用微信授權登錄(如各類微信商城應用系統)。
這樣操作不僅可以實現靜默注冊,對用戶幾乎是無感的,同時也達到了區分用戶,獲取用戶基本信息(頭像,昵稱等)。
使用微信授權的模式可以說一次性替代用戶注冊及用戶登錄。
也是基於上面優勢,我們平常也可以看到在微信公眾號上的應用有不少都是使用微信的這種授權登錄(
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也加快了,可以反復嘗試增加壓力觀察是否存在瓶頸)
最后我們就可以根據自己的業務,添加更多的業務場景進行有針對性的測試。
上面只是一個例子,演示如何通過截獲服務器與微信認證服務器的請求,以達到測試自己業務微信認證登錄的過程。
大家可以利用這個思路,結合自己的需求,進行有針對性的測試。