美文网首页开发技巧
JMeter BeanShell 实现接口签名验签及加解密

JMeter BeanShell 实现接口签名验签及加解密

作者: javacoo | 来源:发表于2021-05-18 15:36 被阅读0次

    在利用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)对响应报文进行验签->解密。

    二,实现

    整体效果如下图:

    微信图片编辑_20210518115705.jpg

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

    • 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包。

    一些信息

    路漫漫其修远兮,吾将上下而求索
    码云:https://gitee.com/javacoo
    QQ群:164863067
    作者/微信:javacoo
    邮箱:xihuady@126.com
    

    相关文章

      网友评论

        本文标题:JMeter BeanShell 实现接口签名验签及加解密

        本文链接:https://www.haomeiwen.com/subject/ymtyjltx.html