Jmeter通过beanshell对http消息进行签名
1.增加前置beanshell脚本
2.beanshell脚本要点
- 通过引入外部jar包,引用相关签名算法,如rsa、ecdsa等
- 通过config.Arguments类的getArgument(0).getValue()获取要发送请求的json body体。调用外部jar包方法进行sha等运算
- http header的rmv和add操作
import com.matrix.common.service.SignatureService;
import org.apache.jmeter.protocol.http.control.Header;
import org.apache.jmeter.config.Arguments;
//获取签名头
public static String getSign(String contentSHA, String date,String nonce ){
String privateKey = vars.get("privateKey");
String method = "GET";
String accept = vars.get("accept");
String contentType = vars.get("contentType");
String nonceHeader = "x-bfs-signature-nonce:"+nonce;
String url = vars.get("createRfqOrderUrl");
//调用jar包中SignatureService的sign方法进行进行签名
String signature = SignatureService.sign(privateKey,method,accept,contentSHA, contentType, date, nonceHeader, url);
return signature;
}
//发送请求前增加签名相关的Header参数
public static void addHeaders( ){
//增加日期头
String date = (new Date()).toString();
sampler.getHeaderManager().removeHeaderNamed("Date");
sampler.getHeaderManager().add(new Header("Date",date));
//增加nonce头
String nonce = "550e8400e29b41d4a716446655440000";
sampler.getHeaderManager().removeHeaderNamed("x-bfs-signature-nonce");
sampler.getHeaderManager().add(new Header("x-bfs-signature-nonce",nonce));
//通过getArgument方法获取json body
Arguments arguments = sampler.getArguments();
String content = arguments.getArgument(0).getValue();
log.info("content="+content);
//增加Content-SHA256 头
String contentSHA = SignatureService.getContentSHA256(content);
log.info("contentSHA="+contentSHA);
sampler.getHeaderManager().removeHeaderNamed("Content-SHA256");
sampler.getHeaderManager().add(new Header("Content-SHA256",contentSHA));
//增加签名头
String signature = getSign(contentSHA,date,nonce);
sampler.getHeaderManager().removeHeaderNamed("Authorization");
sampler.getHeaderManager().add(new Header("Authorization","bfs "+ vars.get("accessKeyId") +":"+signature));
return;
}
addHeaders();
#############################
在利用jmeter进行接口测试或者性能测试的时候,我们需要处理一些复杂的请求,此时就需要利用beanshell脚本了,BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法,所以它和java是可以无缝衔接的。beanshell由于内置了一些特有的变量,没法在一些集成代码工具上去调试。今天就和大家分享下常用的2个代码例子,大家可以直接拿来稍微修改下就可以使用。
Bean Shell内置变量大全
首先大家需要掌握bean shell本身自带的一些内置变量和一些方法。JMeter在其BeanShell中内置了变量,用户是通过这些变量与JMeter进行交互。
1.log 打印日志,写入信息到jmeber.log文件。
2.SampleResult 获取SampleResult对象,能通过这个对象获取想要的信息。
3.Response 获取Response对象,能通过这个对象获取响应信息。
4.Failure 查看接口调使用能否成功,假如返回false是成功的,true是失败的。
5.FailureMessage 失败信息,没有设置的时候失败信息是空的,能set这个信息。
6.ResponseData 获取response body类型是byte[]。
7.ResponseCode 返回接口code成功是200。
8.ResponseMessage 获取msg成功是OK。
9.ResponseHeaders 获取接口服务端返回的头部信息。
10.RequestHeaders 获取用户端请求的头部信息。
11.SampleLabel 获取接口请求的名称。
12.SamplerData 获取请求的url和body。
13.ctx 代表上下文信息,能直接用。
14.vars即JMeterVariables,操作jmeter变量,这个变量实际引用了JMeter线程中的局部变量容器(本质上是Map),常用方法:
a) vars.get(String key):从jmeter中获得变量值;
b) vars.put(String key,String value):数据存到jmeter变量中;
15.prev 获取前面的sample返回的信息,常用方法:
a) getResponseDataAsString():获取响应信息。
b) getResponseCode() :获取响应code。
在写代码的时候,可以直接用上面的变量和方法,参考如下例子。
例子1
使用jmeter的bean shell preprocessor,调用自己写的工具类,实现请求的处理。
步骤如下:
1、 用eclipse把自己写的java代码打包成jar。
2、 把自定义的JAR包放入到jmeter的/lib/ext目录下。
3、 重启jmeter,开始写beanshell脚本。
具体代码:
import net.sf.json.JSONObject;
import ht.test.PluginTest.*;
//请求体,mac做了参数化
String body1 = "{\"ID\":123456,\"RPCMethod\":\"BootInitiation\",\"PROTVersion\":\"1.0.0\",\"MAC\":\"${MAC}\"}";
int bodylenth1 = body1.length();
byte[] lenBytePrefix1 = utils.getBytesOfBig(bodylenth1);
//System.out.println(utils.bytesToHexString(lenBytePrefix2));
//System.out.println(utils.bytesToHexString(body2.getBytes()));
String postdata2 = utils.bytesToHexString(lenBytePrefix1) +
utils.bytesToHexString(body1.getBytes());
String postdata3 = postdata2.replaceAll(" ", "");
//System.out.println("binary data is :" + postdata3);
vars.put("postrequest",postdata3);
//System.out.println(vars.get("postrequest"));
注意:在用system.out.println调试完成后,最终需要注射掉,否则在真正压测的时候会影响压测客户端的性能。
例子2
使用beanshell的assertion断言,完成一些响应结果判断的的操作。
一个比较完整的代码框架如下,大家依葫芦画瓢就行了。
import org.apache.jmeter.assertions;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.assertions.AssertionResult;
import org.json.*;
String response_data = prev.getResponseDataAsString();//获取接口返回的response数据
JSONObject data_obj = new JSONObject(response_data);//转换成json
//判断code是否等于0 如果等于0 再取里面的字段
String code = data_obj.get(“code”);
if(code.equals(“0”))
{
String user_name = data_obj.get(“data”).get(“user”).get(“userName”).toString();
//这里的my_name 是用户自定义的变量或者之前的接口返回获取的
if(user_name.equals(${my_name})){
Failure = false; //设置成false 表示接口跑成功,在结果树中sample是绿色的
//做后续动作
…….
}
else{
//做其他动作
}
}
else
{
Failure = true;//直接判断失败,表示接口跑失败,在结果树中sample是红色的
prev.setStopThread(true);//如果断言失败,后面的接口不需要再跑,直接暂停
}
技巧
高级用法:假如我们希望线程之间共享一个变量,可以利用BeanShell来完成。
JMeter中线程间共享变量可以通过定义属性值来完成,JMeter启动时会读取一些属性文件,比如jmeter.properties、user.properties,这些属性值是可以修改的,通过BeanShell可以对其进行更改。通过props.put()来修改属性,props.get()来获取属性。
Jmeter有哪些Bean Shell
定时器: BeanShell Timer
前置处理器:BeanShell PreProcessor
采样器: BeanShell Sampler
后置处理器:BeanShell PostProcessor
断言: BeanShell断言
监听器: BeanShell Listener
下面先讲一讲 采样器:BeanShell Sampler的用法
在BeanShell Sampler里面写入vars.get和vars.put
查看结果树:
在BeanShell Sampler里面添加方法
查看结果树
引入java文件:
在BeanShell Sampler里面引入java文件
查看结果树
引入class文件:
查看结果树
给自定义的变量赋值
Bean Shell的脚本将test的值传给us
HTTP Request 使用参数化引用us的值
查看结果树:
BeanShell PostProcessor提取json数据
需求:提取sample返回json数据中所有name字段值,返回的json格式如下:
{“body”:{“apps”:[{“name”:”111”},{“name”:”222”}]}}
jmeter中添加后置处理器BeanShell PostProcessor
import org.json.*; String response_data = prev.getResponseDataAsString(); JSONObject data_obj = new JSONObject(response_data); String apps_str = data_obj.get("body").get("apps").toString(); JSONArray apps_array = new JSONArray(apps_str); String[] result = new String[apps_array.length()]; for(int i=0;i<apps_array.length();i++){ JSONObject app_obj = new JSONObject(apps_array.get(i).toString()); String name = app_obj.get("name").toString(); result[i] = name; } vars.put("result", Arrays.toString(result));
jmeter BeanShell断言-----两个变量之间的断言对比
在jmeter的中,断言没法对两个变量的进行对比后判断,只能使用Bean Shell断言来进行,总是有人来问怎么写呢。这里写一个简单的实例吧。
需求:
获取某个用户对应的设备个数接口与数据库查询的个数结果进行对比
Bean Shell断言解决方案:
获取某个用户对应的设备个数接口这个普通的Http接口,这里就不就列出了
与Oracle数据库的查询,如下图
先建立JDBC连接配置,进行JDBC查询,然后用正则提取器
再建立Bean Shell断言,如下
这里介绍下。${streamid_matchNr}是jmeter正则个数的统计
if (!"${streamid_matchNr}".equals("${res_1}"))
表示${streamid_matchNr}与${res_1}不相等则运行下面的代码。
区区几行bean shell快速解决问题
import java.text.DecimalFormat;
String strThreadNum = "${__threadNum}"; //取得当前的虚拟用户ID
int thNum = Integer.parseInt(strThreadNum);
String str = "${iterNO}"; //取得该虚拟用户当前的循环次数
int i = Integer.parseInt(str);
int mobileNumLastFive = thNum * 10000 + i;
DecimalFormat df = new DecimalFormat( "0000000000" );
String fullNum = 4 + df.format(mobileNumLastFive); //格式化成4开头的11位手机号码
System.out.println(fullNum);
vars.put("mobile", fullNum); //将手机号码存入名为mobile的变量,该变量可以在“HTTP请求”中用到
|