1. 程式人生 > >Jmeter-記一次AES加密登入例項

Jmeter-記一次AES加密登入例項

前言

  公司有個網站系統,使用者名稱是明文,密碼是加密的,所以搞了好久才登入進去,因此記錄下艱辛過程。

Part 1   瞭解加密演算法

  找研發同事去了解這個是怎樣一個加密過程,最後得到的結論是:後端會生成一個16位的隨機數,由前端來加密,而前端是用AES的CBC模式加密的。因為前端是用JS實現的,而jmeter是用java,所以不能直接貼前端程式碼。

Part 2   開始百度之旅

  各種百度,最後參照2篇博文,然後copy了程式碼過來優化了下,輸出的密碼密文如下:

參照的部落格地址:

1.https://www.cnblogs.com/artoftest/p/7277996.html

2.https://blog.csdn.net/qq_39820860/article/details/95963968

Part 3   卡住了,不過解決了

  以為這麼容易就結束了嗎?不,還有第3part呢,在加密演算法搞定後,介面一直提示認證失敗,起初以為是網上找的加密演算法跟公司用的不一樣,但是找研發看了,說是一樣的,最後終於在研發同事的提醒下,找到原因了,原來是登入的介面請求時要用到前面那個介面生成的cookie,唉,真心不容易。上面只是簡單貼了下資料,下面具體說下運用吧。

Part 4    完整例項演示

1、新增http請求  獲取登入的key介面(GET):http://../login/getSecretKey

Response Body :{"msg":"success","code":"0","info":{"key":"a2c893cfa0684897"}}

Response headers:

HTTP/1.1 200 OK
Server: openresty/1.11.2.5
Date: Fri, 27 Nov 2020 13:18:12 GMT
Content-Type: text/plain;charset=UTF-8
Content-Length: 62
Connection: keep-alive
Set-Cookie: PHPSESSID=a4b06bc0-9974-4b22-aa25-efcd4e969d4e; Path=/; HttpOnly; SameSite=lax
X-Application-Context: FspService:test:8001
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization

正則表示式提取:

key--從Response Body提取-------------在登入介面會引用到

PHPSESSID--從Response headers提取---------------在資訊頭管理器會引用到

2、新增BeanShell 取樣器  對前面介面提取的key進行AES加密,完整程式碼如下:

//匯入需要的加密包
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

 
    //加密
    public static String encrypt(String data, String key) {
        String ivString = key;
        //偏移量
        byte[] iv = ivString.getBytes();
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            int blockSize = cipher.getBlockSize();
            byte[] dataBytes = data.getBytes();
            int length = dataBytes.length;
            //計算需填充長度
            if (length % blockSize != 0) {
                length = length + (blockSize - (length % blockSize));
            }
            byte[] plaintext = new byte[length];
            //填充
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
            //設定偏移量引數
            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
            byte[] encryped = cipher.doFinal(plaintext);
 
            return Base64.encodeBase64String(encryped);
 
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
 
    //解密
    public static String desEncrypt(String data, String key) {
 
        String ivString = key;
        byte[] iv = ivString.getBytes();
 
        try {
            byte[] encryp = Base64.decodeBase64(data);
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
            byte[] original = cipher.doFinal(encryp);
            return new String(original);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    String data = "abcd1234";//這是明文密碼
        String key = "${key}";//key引用了變數,即前面介面提取出來的key
        String encrypt = encrypt(data,key);
        String desencrypt = desEncrypt(encrypt, key);
        vars.put("enString",encrypt);//把加密的密碼設定為變數enString,供後面登入介面使用
        System.out.println("加密後:"+encrypt);
        System.out.println("解密後:"+desencrypt);
        log.info("加密後:"+encrypt);//列印日誌到控制檯
        log.info("解密後:"+desencrypt);

3、新增http請求  登入介面(POST):http://../login/login

訊息體資料:{"password":"${enString}","userName":"使用者名稱","isMobile":false}

4、HTTP資訊頭管理器

Cookie引用第1個介面生成的PHPSESSID值變數,前面就是被這個變數阻塞了好久

5、以上就完結啦,下面展示下執行緒組框架和debug