在利用JMeter进行接口测试或者性能测试的时候,我们需要处理一些复杂的请求,比如对接口请求参数进行签名,加密,响应数据的验签及解密,以及接口公共参数的处理,此时就需要利用BeanShell脚本了,关于BeanShell的使用小伙伴们可以查看网上相关文章。今天主要和大家分享下接口签名,验签,加解密,以及处理公共参数的例子,希望能帮助到小伙伴们。

一,思路
  • 约定:约定接口有统一的请求及响应格式,如:
    请求协议公共部分

参数

类型

是否必选

描述

appKey

String


应用key

nonce

String


32位UUID随机字串,格式如:296f6fdd570244d98b6046ec135a5b8a

sign

String


签名

timestamp

Long


请求时间戳,

transactionSn

String


交易流水号

parameter

Object


请求的业务对象

响应协议公共部分

参数

类型

描述

code

String

返回码

message

String

返回消息,如错误信息

timestamp

String

响应时间

transactionSn

String

交易流水号

sign

String

签名

data

Object

返回的业务对象

基于此约定,我们才能进一步统一处理。

  • 引入外部签名及加解密工具包
  • JMeter的HTTP请求->请求参数中只填写业务对象(parameter)
  • 利用前置处理器(BeanShell PreProcessor),组装公共请求对象->对业务参数对象进行加密->签名
  • 利用后置处理器(BeanShell PostProcessor)对响应报文进行验签->解密。
二,实现

整体效果如下图:

JAVA 验收接口文档模版 java接口验签实现_JAVA 验收接口文档模版

关于如何建立测试计划,线程组就不用一一描述了,这里只关注核心功能实现。

  • HTTP请求参数(parameter)部分,如:
{
    "idCardNo":"511622198312241918",
    "name":"Leo"
}
  • 接口调用前置处理器-签名/加密(BeanShell PreProcessor),BeanShell代码如下:
//引入依赖
import com.javacoo.service.base.security.util.SignUtil;
import com.javacoo.service.base.security.util.SecurityUtil;
import com.javacoo.service.base.utils.WebUtil;
import com.javacoo.service.base.utils.FastJsonUtil;
import com.javacoo.service.base.BaseRequest;
import java.util.Calendar;
import java.util.Map;
import org.apache.jmeter.config.Arguments; 

//开始处理
log.info("接口调用前置处理器-签名/加密相关处理");
Arguments args = sampler.getArguments(); 

//获取请求参数
String body = args.getArgument(0).getValue();
log.info("业务参数:{}",body);

//获取签名所需参数
String appKey = "${appKey}";
String secretkey = "${secretkey}";
String nonce = WebUtil.genTransSn();
String transactionSn = WebUtil.genTransSn();
Long timestamp = Calendar.getInstance().getTimeInMillis();

//加密
Map bodyMap = FastJsonUtil.stringToCollect(body);
log.info("params:{}",bodyMap);
for(Map.Entry entry : bodyMap.entrySet()){
    entry.setValue(SecurityUtil.encryptDes(entry.getValue(),secretkey));
}
body = FastJsonUtil.toJSONString(bodyMap);
log.info("加密后业务参数:{}",body);

//签名
String sign = SignUtil.clientSign(body,nonce,timestamp.toString(),secretkey);
log.info("sign:{}",sign);

//组装接口请求对象
BaseRequest baseRequest = new BaseRequest();
baseRequest.setAppKey(appKey);
baseRequest.setNonce(nonce);
baseRequest.setTimestamp(timestamp);
baseRequest.setTransactionSn(transactionSn);
baseRequest.setSign(sign);
baseRequest.setParameter(FastJsonUtil.toBean(body));
//转换为JSON字符串
String reqBody = FastJsonUtil.toJSONString(baseRequest);
log.info("reqBody:{}",reqBody);

//重置参数值
args.getArgument(0).setValue(reqBody);
  • 接口调用后置处理程序-验证签名/解密(BeanShell PostProcessor),BeanShell代码如下:
//引入依赖
import com.javacoo.service.base.security.util.SignUtil;
import com.javacoo.service.base.BaseResponse;
import com.javacoo.service.base.utils.FastJsonUtil;
import org.apache.commons.lang3.StringUtils;

//开始处理
log.info("接口调用后置处理器-验证签名");
String responseData = prev.getResponseDataAsString();
log.info("返回数据:{}",responseData);
BaseResponse baseResponse = FastJsonUtil.toBean(responseData, BaseResponse.class);
if(StringUtils.isBlank(baseResponse.getSign()) || baseResponse.getData().get() == null){
    return;
}
//转换
String s = FastJsonUtil.toJSONString(baseResponse.getData().get());
log.info("请求返回业务json:{}",s);
log.info("请求返回签名:{}",baseResponse.getSign());
String secretkey = "${secretkey}";

//验证签名
if (SignUtil.cloudVerifySign(baseResponse.getSign(), s,baseResponse.getTransactionSn(),baseResponse.getTimestamp().toString(), secretkey)) {
       log.info("返回数据合法");
} else {
       log.info("返回数据被篡改");
}
//解密,TODO
三,注意事项及问题
  • JMeter不支持java1.5以后的语法,不支持泛型,如要使用则需要封装成JAR包。

作者:javacoo