当前位置: 首页 > 工具软件 > sign > 使用案例 >

jmeter 接口测试 签名_JMeter处理接口签名(sign)

薛弘厚
2023-12-01

先贴脚本, 大神请直取

新建线程组 → http取样器 → 前置处理器 → bean shell 预处理程序

import org.apache.commons.codec.digest.DigestUtils;

import java.util.Date;

//没有第三方jar包,请放心 import

Date date = new Date();

//将时间戳截取到秒的量级(长度共10位),大神可以考虑地板除,弟中弟请当没看见

String timestamp = String.valueOf(date.getTime()/1000);

//将时间戳赋值给ts变量,方便以 ${ts} 的方式引用

vars.put("ts",timestamp);

//此处的SPhone的值可以用csv参数化

String data = "{\"SPhone\":\"18662255783\",\"EType\":0}";

String key = "a323f9b6-1f04-420e-adb9-b06ty67b0e63";

String bsign = "z417App" + timestamp + data + key;

//MD5加密赋值给sign变量

vars.put("sign",DigestUtils.md5Hex(bsign));

小白请从这里看起

REST api大多会传sign(签名)字段,各接口对sign的内容、方式可能不一样,但一般模式都是从接口的入参中选择部分内容组成一个字符串,然后再拼接一个secretKey或appKey(秘钥,值固定), 最后对这个拼接起来的字符串进行MD5的运算, 将结果赋值给sign; 完整规范的接口文档都会有sign的算法描述。

解题思路

找到签名算法:接口文档为准,secretKey 或 appKey 可以问开发要;

接口的传入的参数不改变,则sign的值就不变:利用这点可以先用接口测试工具(如postman)调试下接口, 在线MD5请移步站长工具;

接口手动调通了,接下来翻译到工具的脚本语言中:说的比较晦涩,继续往下看吧;

特别注意:如果待签名的内容中有中文,需要特别处理下!!踩过坑(这部分会在loadrunner如何处理sign的博客中记录,先挖个坑,以后填)。

接口入参示例

以下是一个传入手机号获取短信验证码的请求消息

{

"AppKey": "z417App",

"AppVer": "1.0.0",

"Data": "{\"SPhone\":\"18662255783\",\"EType\":0}",

"DeviceName": "web",

"DeviceType": "web",

"Lang": "CN",

"Sign": "8011fd9bdacd3372103053b43bef76e7",

"TimeStamp": 1560584745

}

初步分析

这是一串json消息:post方式发送

里面套的Data字段的值有点像json:Data的值是个字符串,不是内层 json

SPhone的值是字符串格式的电话号码:可能是个动态变化的,得用参数化处理下,使它变化起来

sign应该就是今天的主角:sign的算法请仔细阅读接口文档,实在看不懂就问开发

TimeStamp时间戳:一个精确到秒的时间戳

确定可能会动态变换的入参

SPhone字段

Sign字段

TimeStamp字段

签名算法

AppKey + TimeStamp + Data + secretKey 的值拼接在一起组成一个新的字符串,对该字符串进行MD5(32位[小])的运算。(tps:站长工具)

举个不能吃的栗子:

① AppKey 的值是 "z417App"

② TimeStamp 的值是 1560584745

③ Data 的值是 "{\"SPhone\":\"18662255783\",\"EType\":0}"

④ secretKey 的值是 "a323f9b6-1f04-420e-adb9-b06ty67b0e63"

⑤ 拼接成一个字符串:

z417App1560584745{\"SPhone\":\"18662255783\",\"EType\":0}a323f9b6-1f04-420e-adb9-b06ty67b0e63

⑥ MD5运算后的值:8011fd9bdacd3372103053b43bef76e7 → 就可以赋给Sign了

再举个不能吃的栗子:(其他签名算法)

从所有入参中筛选出参数的值不为空(null,"")的集合,将集合中的参数名按照ASCII码从小到大排序(像英语词典), 使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串(sign字段不参与拼接),假设是str1;在str1最后拼接上key=secretKey,得到更长的一个字符串,假设是str2。对str2进行MD5运算,再将得到的字符串转换为大写。

入参举例:

{

"appid": "wxd930u",

"mch_id": 10100,

"device_info": 100,

"body": "{\"EType\":0}",

"DeviceType": "",

"nonce_str": "ibuaiVc",

"sign": "CD198C36632A274C49E5F2F028FA257C",

"source": null

}

第一步:按字典序对有值的入参、按url键值对的方式进行拼接

String str1 = "appid=wxd930u&body={\"EType\":0}&device_info=100&mch_id=10100&nonce_str=ibuaiVc";

第二步:拼接API密钥(secretKey的值:a323f9b6):

String str2 = str1 + "&key=a323f9b6";

第三步:签名MD5(32位[大],可用站长工具)

/**

* 注意java中有自带的MD5方法,是16位以16个元素的形式返回值,大神请自己写,弟中弟请用已有的jar

* md5hex是以32位16进制的小写字符串形式返回

*/

String sign = DigestUtils.md5Hex(str2).toUpperCase();

// 即 sign = "CD198C36632A274C49E5F2F028FA257C"

再看bean shell脚本

import org.apache.commons.codec.digest.DigestUtils; // DigestUtils类中有md5算法

import java.util.Date; // Date类中有获取当前时间戳方法

//没有第三方jar包,请放心 import

Date date = new Date(); // 创建Date对象,取名叫date

//将时间戳截取到秒的量级(长度共10位),大神可以考虑地板除,弟中弟请当没看见

String timestamp = String.valueOf(date.getTime()/1000);

//将时间戳赋值给ts变量,方便以 ${ts} 的方式引用

vars.put("ts",timestamp);

//此处的SPhone的值可以用csv参数化

String data = "{\"SPhone\":\"18662255783\",\"EType\":0}";

String key = "a323f9b6-1f04-420e-adb9-b06ty67b0e63"; // 要拼接的secretKey

String bsign = "z417App" + timestamp + data + key; // 拼接

//MD5加密后,赋值给sign变量

vars.put("sign",DigestUtils.md5Hex(bsign));

在http的取样器中使用 ts 和 sign 的值

{

"AppKey": "z417App",

"AppVer": "1.0.0",

"Data": "{\"SPhone\":\"18662255783\",\"EType\":0}",

"DeviceName": "web",

"DeviceType": "web",

"Lang": "CN",

"Sign": "${sign}",

"TimeStamp": ${ts}

}

问题思考

前面的例子是建立在request body不变的情况下才能成立,如果request body变化呢?比如对手机号(Sphone)做了参数化。处理方式有两种,请戳 jmeter处理动态的签名(sign)内容

欢迎交流指正

 类似资料: