Jmeter 登入使用了 jsencrypt 加密密碼的登入介面

她的包容先生發表於2020-10-13

在一次使用Jmeter做介面效能測試時,發現專案的登入介面,前端傳參時,對密碼進行了加密後傳參,使用密碼明文登入不了。當時想了兩個方案解決這個問題:
方案一:開啟瀏覽器,按下F12,使用一個使用者,輸入正確的祕密從介面登入,檢視登入介面傳入的密碼密文。然後在Jmeter中登入介面的password引數值設定為此密文。
不足:Jmeter啟動多個執行緒時,每個登入使用者的密碼需一樣
方案二:找前端開發詢問密碼加密的方式,然後在Jmeter上編寫js指令碼,按加密祕鑰加密密碼明文得到密文作為變數。然後登入介面引用變數。
當時由於時間緊迫,且週日,開發不在公司,採用了第一種方案。後面有時間,嘗試了第二種方案。以下記錄第二種方案的過程。

步驟1:首先找前端開發詢問了登入介面密碼加密的程式碼和引用的包jsencrypt.js檔案。然後將js檔案放到jmeter啟動jmeter.bat目錄下。前端程式碼如下

const getEncrypt = (data) => {
let publickKey = '公鑰字串'
let crypt = new JSEncrypt()
crypt.setPublicKey(publickKey)
return crypt.encrypt(data)
}

步驟2:開啟Jmeter,在登入介面下方新增JSR223 PreProcessor。編寫指令碼如下:

load("jsencrypt.js"); //載入js檔案

var publicKey = "公鑰字串"; //找開發要的公鑰祕鑰
var crypt = new JSEncrypt();
crypt.setPublicKey(publicKey);//設定公鑰祕鑰
log.info("${passwd}"); //passwd是通過csv獲取到的引數值,列印出密碼明文,用於除錯
var passwdEncryption = crypt.encrypt("${passwd}"); //對密碼明文進行加密
log.info(passwdEncryption); //列印出祕密加密後樣式
vars.put("passwdEncryption", passwdEncryption); //把加密後的放入全域性變數中,然後在登入介面引用${passwdEncryption}

Jmeter截圖如下

步驟3:執行Jmeter指令碼,檢視結果樹,發現登入失敗,提示賬號或密碼錯誤。開啟Jmeter的日誌,出現navigator is not defined in jsencrypt.js錯誤資訊。

因為jsencrypt.js檔案裡面使用到了navigator變數。這個變數在瀏覽器作為全域性變數存在,但在Jmeter上沒有,所以出現了未定義問題。
首先想的是Jmeter沒有,同時這個變數也用不到,所以就把jsencrypt.js中相關navigator的程式碼註釋掉,如下圖。再次執行Jmeter指令碼,報window也未定義,所以關於window程式碼也註釋掉。

navigator和window變數相關程式碼都註釋後,再執行Jmeter指令碼。報了其他問題JSEncrypt is not a function...。

步驟4:感覺註釋掉navigator和window變數行不通,就繼續在網上尋找資料,發現通過在Jmeter中新增var window = this; var navigator = this;定義window和navigator變數。不用修改js檔案,能實現密碼加密和登入成功。

在 JavaScript 中 this 不是固定不變的,它會隨著執行環境的改變而改變。單獨使用 this,會指向全域性(Global)物件。我理解的是會獲取jmeter環境下的全域性物件。最終指令碼如下

var window = this; //定義window全域性變數
var navigator = this; //定義navigator全域性變數
load("jsencrypt.js"); //載入js檔案

var publicKey = "公鑰字串"; //找開發要的公鑰祕鑰
var crypt = new JSEncrypt();
crypt.setPublicKey(publicKey);//設定公鑰祕鑰
log.info("${passwd}"); //passwd是通過csv獲取到的引數值,列印出密碼明文,用於除錯
var passwdEncryption = crypt.encrypt("${passwd}"); //對密碼明文進行加密
log.info(passwdEncryption); //列印出密碼加密後樣式
vars.put("passwdEncryption", passwdEncryption); //把加密後的放入Jmeter全域性變數中,然後在登入介面引用${passwdEncryption}

附錄
在指令碼log.info("${passwd}"); var passwdEncryption = crypt.encrypt("${passwd}");中passwd是通過csv獲取到的引數值,需要加上雙引號,使引數值變為字串型別,不然因為特殊字元(@)會報如下錯誤。

或者沒有特殊字元(@),也會出現引用未定義

參考https://www.cnblogs.com/hong-fithing/p/12175501.html

相關文章