一、首页,了解接口签名规则
签名生成的通用步骤如下:
第一步:设所有发送的数据为集合 M,将集合 M 内非空参数值的参数按照参数名 ASCII 码从小到大排序(字典序),使用 URL 键值对的格式(即 key1=value1&key2=value2…)拼接成字符串 stringA。
特别注意以下重要规则:
◆ 参数名 ASCII 码从小到大排序(字典序);
◆ 如果参数的值为空不参与签名;(如空,或者 null 不参与签名,其他值需要参与签名)
◆ 参数名区分大小写;
第二步:在 stringA 最后拼接上 key 得到 stringSignTemp 字符串,并对 stringSignTemp 进行 MD5 运算,对得到的字符串转化为大写,得到 sign 值。
假设传送的参数如下:
{
"clientId": "ABAEE61B6A2629B598DF57D0F33E3F73",
"method": "qywUser_getUserById",
"id": 1,
"timeStamp": 1561693894,
"version":"1.0"
}
第一步:对参数按照 key=value 的格式,并按照参数名 ASCII 字典序排序如下:stringA=clientId=ABAEE61B6A2629B598D&id=1&method=qywUser_getUserById&timeStamp=1561693894&version=1.0
第二步:拼接客户端密钥:
stringSignTemp=stringA+&key=yrGewXbsp3weUSPcrma9wEN9T3d21P5Ue0S
md5 加密,然后转化成大写得到 sign:
String sign = DigestUtils.md5Hex(bsign).toUpperCase()=474464FA525E039E14E565C0AA179335
最终得到最终发送的数据:
{
"clientId": "ABAEE61B6A2629B598D",
"method": "qywUser_getUserById",
"id": 1,
"timeStamp": 1561693894,
"version":"1.0",
"sign":"474464FA525E039E14E565C0AA179335"
}
二、创建测试计划
新建线程组 → http 取样器 → 前置处理器 → bean shell 预处理程序
解决思路
a. 获取 Key 的值
b. 要提取并编辑 json 格式的内容, 需要用到处理 json 对象的工具包 fastjson
c. TimeStamp 虽然在签名内容之列,但这里不用提取,运行时给它传一个实时的就行
d. 按签名算法完成签名计算
e. 将签名和签名时用的 TimeStamp,替换到 request body 中
beanshell 代码如下:
import org.apache.commons.codec.digest.DigestUtils;
import java.util.Date;
import org.apache.jmeter.config.*;
import com.alibaba.fastjson.JSON; // 文末有fastjson.jar的链接
import com.alibaba.fastjson.JSONObject;
Arguments args = sampler.getArguments(); // 截获请求,包含url、headers 和 body 三部分
Argument arg_body = args.getArgument(0); // 获取请求body
String body = arg_body.getValue(); // 获取body的值保存成字符串
log.info(body); // 打印下看看,跑压测时勿忘把log注掉
JSONObject jso = JSON.parseObject(body); // 把body转成json对象,注意!这里因为body本身就是json字符串,所以用json类处理,xml或其他格式的不能这样处理!!
String clientId = jso.getString("clientId");
String method = jso.getString("method");
String id= jso.getString("id");
String timeStamp = jso.getString("timeStamp");
String version = jso.getString("version");
//将签名传给cliSign参数,使用treemap,可自动进行排序
Map map = new TreeMap();
map.put("clientId", clientId);
map.put("method", method);
map.put("id", id);
map.put("timeStamp", timeStamp);
map.put("version", version);
//URLEncoder.encode(value, "UTF-8") 对中文进行格式化,这里不需要
StringBuffer sb = new StringBuffer();
for (Map.Entry entry : map.entrySet()) {
sb.append(entry.getKey() + "=" + entry.getValue());
sb.append("&");
}
String s = sb.toString();
if (s.endsWith("&")) {
s = org.apache.commons.lang.StringUtils.substringBeforeLast(s, "&");
}
log.info("Map转换为URL编码"+s);
//将时间戳截取到秒的量级(长度共10位)
Date date = new Date();
String timestamp = String.valueOf(date.getTime()/1000);
String bsign = s + "&key=yrGewXbsp3weUSPcrma9wEN9T3d21P5Ue0S";
log.info("待加密字符串为:"+bsign);
String sign = DigestUtils.md5Hex(bsign);
log.info("加密后的值:"+sign);
//替换 timestamp 和 sign 字段的值到jsonObject
jso.put("timeStamp",Integer.parseInt(timestamp));
jso.put("sign",sign.toUpperCase()); //md5加密,然后转化成大写得到sign
body = jso.toString();
arg_body.setValue(body); // 将新body替换到取样器的参数中,实现了截获 → 修改 → 发送修改后的内容
下载 fastjson 放到 jmeter 的 plugins 专用目录,如我的:
E:\DownLoad\Software\apache-jmeter-3.1\lib\ext
fastjson 下载地址:
https://github.com/alibaba/fastjson/releases
参考文档来源:
https://www.cnblogs.com/51benpao/p/13118078.html
https://www.cnblogs.com/z417/articles/13785978.html