有些接口的請求參數是加密的,返回的接口內容也是須要解密才能看到。html
好比當咱們訪問下面這個登錄的接口時,請求參數帳號和密碼都是須要加密,經過parms參數傳過去,服務器才能識別到python
沒加密的時候,請求參數應該是json
{ "params": { "username": "test", "password": "123456" } }
返回的結果,解密後應該是api
{ "code": 0, "msg": "login success!", "datas": { "username": "test", "token": "a003442ffc9645af181d8c768bd8758a250ba6d6" } }
像這種接口,作接口自動化的時候,請求參數應該用未加密以前的測試參數,這樣方便維護和修改,在發請求的過程當中先對請求參數加密。
具體的加密規則和方法,得看開發的加密規則了,好比參考這篇的加密http://www.javashuo.com/article/p-rnlakoqm-ew.html服務器
寫腳本的時候,yaml文件寫未加密的時候,原始的測試數據app
- config: name: testcase description variables: {} - test: name: /api/v2/login request: headers: Content-Type: application/json User-Agent: Fiddler json: params: password: '123456' username: test method: POST url: http://49.235.92.12:9000/api/v2/login setup_hooks: - ${setup_request($request)} validate: - eq: - status_code - 200 - eq: - headers.Content-Type - application/json - eq: - content.code - 0 - eq: - content.msg - login success!
接下來只須要把 params 下的參數作加密就能夠了,這裏用到setup_hooks函數實現, ${setup_request($request)}
函數在debugtalk.py裏面去寫一個dom
setup_hooks用於在 HTTP 請求發送前執行 hook 函數,主要用於準備工做;也能夠實現對請求的 request 內容進行預處理。
如下是官方文檔給的案例函數
def setup_hook_prepare_kwargs(request): if request["method"] == "POST": content_type = request.get("headers", {}).get("content-type") if content_type and "data" in request: # if request content-type is application/json, request data should be dumped if content_type.startswith("application/json") and isinstance(request["data"], (dict, list)): request["data"] = json.dumps(request["data"]) if isinstance(request["data"], str): request["data"] = request["data"].encode('utf-8')
能夠依着葫蘆畫瓢測試
from cryptography.hazmat.primitives import padding from cryptography.hazmat.primitives.ciphers import algorithms from Crypto.Cipher import AES from binascii import b2a_hex, a2b_hex import json ''' AES/CBC/PKCS7Padding 加密解密 環境需求: pip3 install pycryptodome ''' class PrpCrypt(object): def __init__(self, key='1234123412341234'): self.key = key.encode('utf-8') self.mode = AES.MODE_CBC self.iv = b'0102030405060708' # block_size 128位 # 加密函數,若是text不足16位就用空格補足爲16位, # 若是大於16當時不是16的倍數,那就補足爲16的倍數。 def encrypt(self, text): cryptor = AES.new(self.key, self.mode, self.iv) text = text.encode('utf-8') # 這裏密鑰key 長度必須爲16(AES-128), # 24(AES-192),或者32 (AES-256)Bytes 長度 # 目前AES-128 足夠目前使用 text=self.pkcs7_padding(text) self.ciphertext = cryptor.encrypt(text) # 由於AES加密時候獲得的字符串不必定是ascii字符集的,輸出到終端或者保存時候可能存在問題 # 因此這裏統一把加密後的字符串轉化爲16進制字符串 return b2a_hex(self.ciphertext).decode().upper() @staticmethod def pkcs7_padding(data): if not isinstance(data, bytes): data = data.encode() padder = padding.PKCS7(algorithms.AES.block_size).padder() padded_data = padder.update(data) + padder.finalize() return padded_data @staticmethod def pkcs7_unpadding(padded_data): unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() data = unpadder.update(padded_data) try: uppadded_data = data + unpadder.finalize() except ValueError: raise Exception('無效的加密信息!') else: return uppadded_data # 解密後,去掉補足的空格用strip() 去掉 def decrypt(self, text): # 偏移量'iv' cryptor = AES.new(self.key, self.mode, self.iv) plain_text = cryptor.decrypt(a2b_hex(text)) # return plain_text.rstrip('\0') return bytes.decode(plain_text).rstrip("\x01").\ rstrip("\x02").rstrip("\x03").rstrip("\x04").rstrip("\x05").\ rstrip("\x06").rstrip("\x07").rstrip("\x08").rstrip("\x09").\ rstrip("\x0a").rstrip("\x0b").rstrip("\x0c").rstrip("\x0d").\ rstrip("\x0e").rstrip("\x0f").rstrip("\x10") def dict_json(self, d): '''python字典轉json字符串, 去掉一些空格''' j = json.dumps(d).replace('": ', '":').replace(', "', ',"').replace(", {", ",{") return j def setup_request(request): pc = PrpCrypt('12345678\0\0\0\0\0\0\0\0') # 初始化密鑰 params = request.get("json").get("params") print("加密前:%s" % params) # 對params加密 en_params = pc.encrypt(json.dumps(params)) print("解密後:%s" % en_params) request["json"]["params"] = en_params
運行用例結構加密
D:\soft\HELL\DEMO>hrun login_decrype.yml /api/v2/login 加密前:{'password': '123456', 'username': 'test'} 解密後:3DBF6BE0F8549A98AA81B629A028E487BA2EBE85EF1BC9FE7105F5FE833F1DF26F022E404EFBDAD5A5DF1A7B7FEDA16C INFO POST http://49.235.92.12:9000/api/v2/login INFO status_code: 200, response_time(ms): 467.89 ms, response_length: 209 bytes INFO start to validate. . ---------------------------------------------------------------------- Ran 1 test in 0.574s OK INFO Start to render Html report ... INFO Generated Html report: D:\soft\HELL\DEMO\reports\1571850793.html