测试接口遇到APP加密?先来了解一下算法思路~

背景

服务端与客户端进行http通讯时,为了防止被爬虫,数据安全性等,引入APP通信加密,简单来说,就是引入签名sign,APP的所有请求都会经过加密签名校验流程。常见的加密方案有AES加密,RSA加密,MD5加密等。由于引入签名sign请求头,我们在测APP接口的时候,不填签名数据的话,都会被服务端加密签名校验所拦截,这对我们测接口造成了极大的困扰

  1. {

  2. "msg": "鉴权失败",

  3. "code": 99999,

  4. "data": {}

  5. }

解决方案

叫开发在测试环境关闭签名验证
通过抓包把APP的请求头和请求参数抓下来,通过postman测试
询问开发具体的加密过程,复写一套加密算法,自己生成加密数据

方案分析

测试环境关闭签名验证,可能对代码改动比较大,容易留下坑,有可能上线部署时忘记打开签名验证,这会造成极大的影响;也有可能改动不大,开发代码比较规范,上线比较规范;(每个公司情况不一样~)可以作为备选方案。

每次抓包时,请求参数都是固定的,而签名数据又是随着请求参数变化而变化,这对于测试接口的多场景比较麻烦,每点一次就抓包一次;有时候前后端还没联调,让你提前介入接口测试,没有页面怎么抓包,抛弃。

复写过程可能比较复杂,可能比较简单,需要开发协助说明整个加密过程(一杯奶茶就好了)复写过程中又可以锻炼自己的code能力,推荐。

方案实现过程

验签说明

参数名按ASCII码从小到大排序(字典序)如果参数的值为空(null值,空格、空字符串)不参与签名,参数名区分大小写;如参数的类型为复合类型不参与签名(如:List[Map]类型或List[String]类型或List[int]类型)。

使用URL键值对的格式(key1=value1&key2=value2…)拼接成待签名的字符串plain,在plain最后拼接上key(密钥),plain=plain+”&key=分配的密钥”,再将plain进行签名运算sign=Base64(MD5(plain))。

sign字符串放在http报文头中X-Sign字段。

验签步骤拆解

  • 参数名按ASCII码从小到大排序
  • 参数值为空(null值,空格、空字符串)不参与签名
  • 参数值为复合类型(对应Python中的dict、list)不参与签名
  • 拼接键值对,格式为key1=value1&key2=value2…
  • 键值对后面拼接key(密钥)
  • 键值对字符串先经过MD5加密,再进行base64编码
py实现
  1. import hashlib

  2. import base64

  3. key = '123456'

  4. class Sign:

  5. @classmethod

  6. def get_sign(cls, data):

  7. # 不改变传入的data=>直接对字典进行复制

  8. data = data.copy()

  9. # 首先判断字典是否空,为空直接加密

  10. if not data:

  11. string = ''

  12. else:

  13. # 非空字典,过滤value为空和嵌套字典、列表

  14. for k, v in list(data.items()):

  15. if isinstance(v,str):

  16. v = v.replace(" ", "").replace("\n", "")

  17. data[k] = v

  18. if v == '' or v is None or isinstance(v,(dict,list)):

  19. data.pop(k)

  20. # 对字典进行ASCII码排序

  21. new_list = sorted(data.items())

  22. alist = ['&' + str(i[0]) + '=' + str(i[1]) for i in new_list]

  23. string = ''.join(alist)

  24. return {"X-Sign": cls.encry(string)}

  25. @classmethod

  26. def encry(cls, string):

  27. """

  28. 加密算法

  29. :param string: 要加密的字符串

  30. :return: 字符串

  31. """

  32. if string:

  33. sign = string[1:] + '&key=' + key

  34. else:

  35. sign = 'key=' + key

  36. m = hashlib.md5()

  37. m.update(sign.encode("utf8"))

  38. encodeStr = m.hexdigest()

  39. base_code = base64.b64encode(encodeStr.encode('utf-8'))

  40. return base_code.decode( )

因为有用到dict.pop()方法,这会对原来的data进行改变,所以我们传入data的时候,对data进行浅拷贝:

data = data.copy()

字符串要去除空格、换行符,实际服务端进行加密生成时,也会对字符串进行去除空格、换行符:

  1. if isinstance(v,str):

  2. v = v.replace(" ", "").replace("\n", "")

  3. data[k] = v

 算法验证

  1. import requests

  2. data ={

  3. "mercId": "888000000000001",

  4. "sysCnl": "IOS",

  5. "orderTypes": [0, 1, 2, 3, 4, 5, 6, 7, 9, 10],

  6. "platform": "LXMALL",

  7. "limit": 20,

  8. "page": 1,

  9. "timestamp": "1625881419"

  10. }

  11. sign_data = Sign.get_sign(data)

  12. headers = {

  13. "X-Token" : "08fa6dad125d30842c58d9bea6059ace",

  14. "X-APPVer": "1.5",

  15. "X-SignVer": "v1",

  16. "Content-Type": "application/json"

  17. }

  18. headers |= sign_data

  19. url = base_url + 'order/list'

  20. r = requests.post(url,json = data,headers = headers)

  21. print(r.json())

成功打印输出返回参数,大功告成~

api集成

你可以将生成加密数据做成一个api提供给小伙伴使用,传入待加密的请求报文,返回加密数据,小伙伴复制粘贴加密数据到请求头,即可完成接口测试。

jmeter集成

因为jmeter里面的beanshell用的是Java语法,可以直接喊开发(Java后端或者Android开发)直接帮你打个jar包,直接调用即可。

//找不到以前的脚本,大家可以去网上搜索一下的源码,大致是下面的import com.xxx.xxxx.Sign;String SamplerData=prev.getSamplerData();String signData = Sign.getSign(SamplerData);http://log.info("签名数据是"+signData);
总结:

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

 

          视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。

  • 19
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值