httprunner学习23-加解密
发布日期:2021-05-09 09:02:29 浏览次数:4 分类:博客文章

本文共 5115 字,大约阅读时间需要 17 分钟。

前言

有些接口的请求参数是加密的,返回的接口内容也是需要解密才能看到。

加密接口

比如当我们访问下面这个登陆的接口时,请求参数账号和密码都是需要加密,通过parms参数传过去,服务器才能识别到

没加密的时候,请求参数应该是

{	"params": {		"username": "test",		"password": "123456"	}}

返回的结果,解密后应该是

{	"code": 0,	"msg": "login success!",	"datas": {		"username": "test",		"token": "a003442ffc9645af181d8c768bd8758a250ba6d6"	}}

像这种接口,做接口自动化的时候,请求参数应该用未加密之前的测试参数,这样方便维护和修改,在发请求的过程中先对请求参数加密。

具体的加密规则和方法,得看开发的加密规则了,比如参考这篇的加密

hrun脚本编写

写脚本的时候,yaml文件写未加密的时候,原始的测试数据

-   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里面去写一个

setup_hooks

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 paddingfrom cryptography.hazmat.primitives.ciphers import algorithmsfrom Crypto.Cipher import AESfrom binascii import b2a_hex, a2b_heximport 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 jdef 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'}解密后:3DBF6BE0F8549A98AA81B629A028E487BA2EBE85EF1BC9FE7105F5FE833F1DF26F022E404EFBDAD5A5DF1A7B7FEDA16CINFO     POST http://49.235.92.12:9000/api/v2/loginINFO     status_code: 200, response_time(ms): 467.89 ms, response_length: 209 bytesINFO     start to validate..----------------------------------------------------------------------Ran 1 test in 0.574sOKINFO     Start to render Html report ...INFO     Generated Html report: D:\soft\HELL\DEMO\reports\1571850793.html
上一篇:python笔记44-HTTP对外接口sign签名
下一篇:Linux学习26-linux查看某个时间段的日志(sed -n)-史上最详细

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2025年04月07日 03时09分40秒