实际业务中,会要求 HTTP 协议中附加 MD5 校验字段, 防止请求参数被恶意篡改, 对于开发同学来说, 这是个很简单的需求。 但是给自动化测试增加了难度, Jmeter 原生不支持这个功能,应测试同学要求,开发了一个简单的小插件。

一、功能分析

  1. MD5 值生成规则:

    Step1, HTTP 请求增加新参数 ct, 值为当前时间毫秒数;

    Step2, 获取HTTP 请求所有参数,放入 list;

    Step3, List 增加新参数 key, 值根据通信协议的双方约定(不在 http请求中传递 );

    Step4, 把 List 按参数名进行排序,把排序后的参数值进行拼接, 对拼接结果执行 MD5 运算;

    Step5, Http请求增加新参数 code, 值是 Step4 计算得出的值。

  注:不同业务此规则可能略有差异,请根据实际情况实现。

  2. MD5 值需要在 HTTP 请求之前添加 (属于 Jmeter 前置处理器范围)。

二、需要解决的问题

  1. 在 Jmeter 的 HTTP 请求中获取参数、 增加参数

  2. 实现 MD5 的具体逻辑

  3. 在合适的时机把生成的 MD5 校验值附加到 HTTP 请求参数中

  4. 集成到 Jmeter 菜单中,方便使用。

三、解决步骤

  1. 因之前没有 Jmeter 插件开发经验, 需要先学习一下如何开发。 网上搜集了一下资料没有太明确的方案;不过Jmeter本身有很多插件,就从这里入手,分析一下现有插件的实现方式,然后用相同的方式来完成插件。

  2. 到 Apache 官网 下载 Jmeter 的源代码(我使用的2.11版), 根据 Jmeter 界面中看到的关键字来定位插件代码位置。

  3. 开发的是 Http Sampler 插件,那么,我们先搜索一下Http Sampler关键字, 可以找到 HttpSampler.java;阅读代码可以得到问题1的答案。

  4. 问题2不在赘述。

  5. 分析问题3, 我们需要在 HTTP 请求发送前, 进行插件调用, 可以得知这个插件应该是属于前置处理器范围的。 通过分析前置处理器的代码应该可以解决这个问题。Jmeter 插件中第一个前置处理器是 BeanShell PreProcessor, 用 BeanShell 和 PreProcessor 关键字查找源代码, 查到了类 BeanShellPreProcessor.java;阅读这个类及父类代码可以得到问题3、问题4的答案。

四、具体代码

1. MD5PreProcessor.java

 public class MD5PreProcessor  extends AbstractTestElement implements TestStateListener, PreProcessor, Serializable {

     private static final long serialVersionUID = -1L;
private static final Logger LOGGER = LoggingManager.getLoggerForClass(); /**
* Default constructor.
*/
public MD5PreProcessor() {
} @Override
public void testStarted() {
} @Override
public void testStarted(String host) {
} @Override
public void testEnded() {
} @Override
public void testEnded(String host) {
} /*
* ------------------------------------------------------------------------
* Methods implemented from interface org.apache.jmeter.config.Modifier
* ------------------------------------------------------------------------
*/ @Override
public void process() {
Sampler sam = getThreadContext().getCurrentSampler();
HTTPSamplerBase sampler = null;
if (!(sam instanceof HTTPSamplerBase)) {
return;
} else {
sampler = (HTTPSamplerBase) sam;
} // 排序参数和header(appversion, os)
java.util.List<KeyValue> list = new ArrayList<KeyValue>(); sampler.addArgument("ct", System.currentTimeMillis() + ""); // 添加参数列表
Arguments arguments = sampler.getArguments();
PropertyIterator iter = arguments.iterator();
while(iter.hasNext()) {
Argument arg = getFromJMeterProperty(iter.next());
KeyValue kv = new KeyValue(arg.getName(), arg.getValue());
list.add(kv);
} // 添加header: os appVersion
HeaderManager headerManager = sampler.getHeaderManager();
for(int i = 0; i < headerManager.getHeaders().size(); i++) {
Header a = headerManager.getHeader(i);
if("os".equals(a.getName()) || "appVersion".equals(a.getName())) {
list.add(new KeyValue(a.getName(), a.getValue()));
}
} // 加盐
list.add(new KeyValue("key", "+MrK}6seb#$E")); StringBuffer sbu = new StringBuffer(); // 按顺序拼接所有参数值
Collections.sort(list);
for(KeyValue kv : list) {
//LOGGER.info("key: "+kv.getKey()+", value:"+kv.getValue());
sbu.append(kv.getValue());
} try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] md5sum = md.digest(URLEncoder.encode(sbu.toString(), "UTF-8").getBytes());
String md5Code = new BigInteger(1, md5sum).toString(16); while(md5Code.length() < 32 ){
md5Code = "0"+md5Code;
} LOGGER.info("before: "+sbu.toString()+",encode:"+URLEncoder.encode(sbu.toString(), "UTF-8")+",end:"+md5Code);
sampler.addArgument("code", md5Code);
} catch(Exception e) {
e.printStackTrace();
} } private Argument getFromJMeterProperty(JMeterProperty o) {
return (Argument)o.getObjectValue();
} /*
* ------------------------------------------------------------------------
* Methods
* ------------------------------------------------------------------------
*/
private class KeyValue implements Comparable<KeyValue> {
private String key;
private String value; public KeyValue(String key, String value) {
this.key = key;
this.value = value;
} @Override
public int compareTo(KeyValue o) {
int result = this.key.compareTo(o.key);
if(result == 0) {
result = this.value.compareTo(o.value);
} return result;
} public String getKey() {
return key;
} public String getValue() {
return value;
}
} }

2. Md5PreProcessorGui.java

public class Md5PreProcessorGui extends AbstractPreProcessorGui {
private static final long serialVersionUID = 100L;
private static final Logger LOGGER = LoggingManager.getLoggerForClass(); public Md5PreProcessorGui() {
createGui();
} public String getStaticLabel() {
return "MD5 Encode";
} public String getLabelResource() {
return getClass().getCanonicalName();
} public void configure(TestElement element) {
super.configure(element);
} public TestElement createTestElement() {
MD5PreProcessor sampler = new MD5PreProcessor();
modifyTestElement(sampler);
return sampler;
} public void modifyTestElement(TestElement element) {
element.clear();
configureTestElement(element);
} public void clearGui() {
super.clearGui(); } private void createGui() {
setLayout(new BorderLayout(0, 5));
setBorder(makeBorder()); this.setLayout(new BorderLayout(0, 5));
this.setBorder(this.makeBorder());
this.add(this.makeTitlePanel(), "North"); VerticalPanel mainPanel = new VerticalPanel();
add(mainPanel, "Center"); }
}

Jmeter MD5插件的更多相关文章

  1. JMeter Plugin插件配置及远程监控

    下载jmeter plugins 插件: https://jmeter-plugins.org/downloads/all/ 官网建议我们直接下载plugins-manager.jar,然后进行可选择 ...

  2. 【JMeter】插件安装

    安装插件的方法有两种,一种是传统的方式,即官网下载,本地配置,重启jmeter.现在有一种快捷的方法可以自定义安装插件-插件管理器 JMeter 插件管理器的使用方法很简单:不要手动安装各种插件,它提 ...

  3. JMeter开发插件——图片验证码识别

    我们在性能测试中总会时不时地遭遇到来自于应用系统的各种阻碍,图片验证码就是一类最常见的束缚,登录或交易时需要按照图片中的内容输入正确的验证信息后,数据才可以提交成功,这使得许多性能测试工具只能望而却步 ...

  4. 如何为Apache JMeter开发插件(一)

    本文转载于http://blog.csdn.net/column/details/12925.html,作者:xreztento 作者写的很精华,我打算在此系列操作一遍后,加多点截图,便于更多人更快上 ...

  5. 如何为Apache JMeter开发插件(二)—第一个JMeter插件

    文章内容转载于:http://lib.csdn.net/article/softwaretest/25700,并且加上个人一些截图 本篇将开启为JMeter开发插件之旅,我们选择以Function(函 ...

  6. JMeter扩展插件实现对自定义协议进行支持 转

    本文版权归xmeter.net 所有.欢迎转载,转载请注明出处. 摘要## JMeter本身提供了插件机制,允许第三方扩展JMeter以支持JMeter不支持的协议的测试.本文以扩展一个简单的Apac ...

  7. Jmeter websocket插件安装与使用

    Jmeter websocket插件安装与使用 Apache JMeter是Apache组织开发的基于Java的压力测试工具.用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试 ...

  8. Jmeter官方插件实现Dubbo接口测试

    目前主流的分布式框架有Dubbo和SpringCloud, SpringCloud是基于Http协议的分布式框架,Dubbo是基于RPC的分布式框架,Jmeter没有内置对Dubbo接口的支持,很难直 ...

  9. 四、Jmeter安装插件

    Jmeter安装插件方法和使用 1-下载Jmeter管理jar包 下载地址:https://jmeter-plugins.org/install/Install/ 2-点击下载 plugins-man ...

随机推荐

  1. Node.js系列-express(上)

    前言 Node.js系列的第一篇:http,大概描述了通过使用node.js内置的api创建一个服务并监听request实现简单的增删改查.现在,我们就通过通读express官网及使用express框 ...

  2. MonogoDB 查询小结

    MonogoDB是一种NoSQL数据库 优点: 1.数据的存储以json的文档进行存储(面向文档存储) 2.聚合框架查询速度快 3.高效存储二进制大对象 缺点: 1.不支持事务 2.文件存储空间占用过 ...

  3. Windows系统安装pip方法

    pip是一款非常方便的python包管理工具,本文主要介绍在windows 10系统下安装pip方法. 1. 下载pip 地址:https://pypi.python.org/pypi/pip#dow ...

  4. windows系统下安装Eclipse for PHP

    第一步: 如果机器上没有java运行环境,请先安装   第二步: 下载eclipse,下载地址: http://www.eclipse.org/downloads/ 选择对应版本,本人选择的是64位版 ...

  5. Spring MVC的配置和使用

    Spring MVC的配置和使用 笔记仓库:https://github.com/nnngu/LearningNotes Spring MVC需要的jar包 文章中 Spring MVC 使用的版本是 ...

  6. SDN第二次上机作业

    作业链接 安装floodlight 生成拓扑并连接控制器floodlight,利用控制器floodlight查看图形拓扑 from mininet.topo import Topo class MyT ...

  7. Ubuntu16.04解决无法切换root权限的问题

    在su root时发现无法切换到root权限.显示: /usr/local/bin/zsh 没有文件或目录 想了想问题所在,突然想起来前段时间想要更换shell主题,于是装了zsh和oh-my-zsh ...

  8. Gitbucket—快速建立自己的Github

    GitBucket是一个用Scala语言编写的类似Github的应用,界面非常相似.它非常容易安装–容易到你只需要把它的war文件扔到tomcat中,然后启动tomcat就直接可以访问了.或者直接ja ...

  9. maven项目打包的时候,*Mapper.xml 文件会打不不进去解决办法

    打包的时候,不同版本的 Eclipse 还有IDEA 会有打包打不进去Mapper.xml 文件,这个时候要加如下代码, 在<build> 标签内加入即可 <resources> ...

  10. Java经典编程题50道之四十八

    某个公司采用公用电话传递数据,数据是四位的整数,在传递过程中是加密的,加密规则如下: 每位数字都加上5,然后用和除以10的余数代替该数字, 再将第一位和第四位交换,第二位和第三位交换. public ...