場景
我們在寫服務端接口時候,往往需要考慮安全問題,最基本的一點就是接口需要按照約定的規則進行簽名校驗。一旦接口校驗簽名,就意味着我們用Postman不能想以前那樣順利的測試了,服務端必定會返回簽名失敗。我們在本地開發時候,一定有不少開發同學是通過註釋掉驗籤代碼來繞開簽名,但往往提交代碼時候又不小心提交上去。靈活點的簽名校驗可能會忽略掉來自本機請求的驗籤,我們這裏假設系統設計的沒這麼靈活,而且即使這樣靈活設計也還是解決不了外網要測試dev qa環境的接口無法通過驗籤的問題。下面我們就利用Postman強大的Pre-request Script功能來實現自動爲每個請求生成服務端需要的簽名參數。
Pre-request Script
在開始編寫案例之前,先簡單介紹一下Postman的Pre-request Script到底是個什麼東西?從字面意思能猜測出這是一個在請求之前會執行的腳本,我們看下官方給出的流程圖,就可以證明我們的猜想。
Pre-request Script是通過Postman的沙盒(Sandbox)來實現的,而Sandbox是一個JavaScript執行環境,裏面內置了一部分常用的JS庫和函數(下面會介紹到)。所以我們其實是通過編寫JavaScript代碼,代碼在請求發出前先被執行,從而達到自動生成簽名的目的。
實戰
先切換到Pre-request Script
選項卡,開始編寫JavaScript代碼。
假設服務端的簽名算法如下:所有請求參數都放在Body
裏以json
格式提交,裏面必須包含一個當前時間戳ts
以及簽名後得到的sign
。對body中除了sign
以外的所有字段簽名(暫時不考慮json有數組的情況),先按照key升序
排列,然後以key=value
的形式用&
拼接字符串,最後用簽名密鑰signKey
對拼接後的字符串進行SHA1
簽名得到sign
。我們直接貼代碼吧。
(function () {
var data = JSON.parse(request.data);
var signKey = pm.environment.get('signKey');
var sign = calcSign(data, signKey);
pm.globals.set('sign', sign);
})();
function calcSign(data, signKey) {
delete data['sign'];
var keys = [];
for(var k in data) {
keys.push(k);
}
keys.sort();
var kv = [];
for (var v of keys) {
kv.push(v + '=' + data[v]);
}
var kvStr = kv.join('&');
var sign = CryptoJS.HmacSHA1(kvStr, signKey).toString();
return sign;
}
我們還需要在請求的Body
里加上ts
和sign
字段,而且必須用雙引號括起來,否則會報錯。還要在環境變量或全局變量(視情況而定)裏設置signKey
字段,如圖所示。
代碼中使用到了Postman Sandbox的一些常用的內置函數,這裏簡單介紹一下。Sandbox內置的類庫以及完整的Postman API介紹請看最下面的文檔,這裏無法一一羅列和演示。
(function(){ ... })()
:jQuery的寫法,Sandbox內置了jQuery庫。pm.environment.get(variableName)
:獲取某個環境變量的值,也可以寫成 postman.getEnvironmentVariable(variableName)。pm.globals.set(variableName, variableValue)
:設置某個全局變量,也可以寫成 postman.setGlobalVariable(variableName, variableValue)。CryptoJS.HmacSHA1()
:內置的CryptoJS庫,幾乎涵蓋所有加密算法,本案例使用了SHA1,大家根據具體簽名規則來選擇。{{$timestamp}}
:動態返回當前時間戳。類似的語法還有{{$guid}}
生成唯一ID,{{$randomInt}}
生成0到1000的隨機整數。
如果每個請求都要加簽名,不必爲每個請求都寫一份重複的Pre-request Script代碼。可以在收藏
或者文件夾
級別統一設置,這樣該收藏或文件夾下每一個請求都能執行到。
以上只是Pre-request Script的一個常見的應用場景,它的用途非常之廣,等待你去探索!