JMeter进阶使用变量及BeanShell 预处理程序实现复杂调试

JMeter进阶使用变量及BeanShell 预处理程序实现复杂调试

有一些测试需要做一些预处理程序才能做http请求,在JMeter下可以通过使用参数+BeanShell 预处理程序加工后再发起请求即可。例oauth服务需要通过username,password,client_id,client_secret,grant_type进行请求,这里的密码涉及安全性不能用明文进行传输,需要做预处理

应用提供如下信息:

用户名:username=user

密码:password=888888

盐值:salt=2gjokme8k5p0u3n8ca1n

客户端ID:client_id=test

客户端秘钥:client_secret=16air0bu4l0yjnfkkxfc

授权模式:grant_type=password

发送密码的规则为password=sha(md5(8888882gjokme8k5p0u3n8ca1n))=a43dd2bfc28bbaf137ab5a45d634f44eed06adcf

这里需要先将(密码+盐值)先进行md5,再进行sha才是要发送的最终参数,这里如果只测试一个用户时间,先通过其它程序取得再传入也是很方便,但如果需要做多个用户的测试就非常麻烦了,需要不停的去加工后才能在jmeter里更换,调试起来不方便,如果用参数+BeanShell 预处理程序就可以很方便处理了

下面来实际验证

验证请求

JMeter进阶使用变量及BeanShell 预处理程序实现复杂调试_jmeter

成功返回

JMeter进阶使用变量及BeanShell 预处理程序实现复杂调试_变量_02

下面用参数+BeanShell 预处理程序来实现

定义参数

如果换个用户,只需修改这里即可

JMeter进阶使用变量及BeanShell 预处理程序实现复杂调试_压力测试_03

HTTP请求里值用${xxxx}来定义变量参数,来接收定义的参数或BeanShell 预处理程序生成的变量,这里${passwordPar}是BeanShell 预处理程序生成的

JMeter进阶使用变量及BeanShell 预处理程序实现复杂调试_jmeter_04

BeanShell预处理程序

JMeter进阶使用变量及BeanShell 预处理程序实现复杂调试_压力测试_05

处理程序

import sun.misc.BASE64Encoder;

import java.io.UnsupportedEncodingException;

import java.security.MessageDigest;

import java.security.NoSuchAlgorithmException; 

import java.util.Arrays;

import java.util.Map;

import java.util.Set;

import com.alibaba.fastjson.JSONArray;

import com.alibaba.fastjson.JSONObject;

    public static String md5AndSha(String inputText)

    {

        return sha(md5(inputText));

    }

    public static String md5(String inputText) {

        return encrypt(inputText, "md5");

    }

    public static String sha(String inputText) {

        return encrypt(inputText, "sha-1");

    }

    public static String encrypt(String inputText, String algorithmName) {

        if (inputText == null || "".equals(inputText.trim())) {

            thrownew IllegalArgumentException("请输入要加密的内容");

        }

        if (algorithmName == null || "".equals(algorithmName.trim())) {

            algorithmName = "md5";

        }

        String encryptText = null;

        try {

            MessageDigest m = MessageDigest.getInstance(algorithmName);

            m.update(inputText.getBytes("UTF8"));

            byte[] s = m.digest();

            return hex(s);

        } catch (NoSuchAlgorithmException e) {

            e.printStackTrace();

        } catch (UnsupportedEncodingException e) {

            e.printStackTrace();

        }return encryptText;

    }

public static String hex(byte[] arr) {

 StringBuffer sb = new StringBuffer();

for (int i = 0; i < arr.length; ++i) {

  sb.append(Integer.toHexString((arr[i] & 0xFF) | 0x100).substring(1, 3));

 }

return sb.toString();

}

public static String MD5(String data) throws Exception {

  MessageDigest md = MessageDigest.getInstance("MD5");

byte[] array = md.digest(data.getBytes("UTF-8"));

    StringBuilder sb = new StringBuilder();

    for (byte item : array) {

      sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));

    }

    return sb.toString().toUpperCase();

}

public   String generateSignature( Map  data, String key, String signType) throws Exception {

       // Set<String> keySet = data.keySet();

       Set  keySet = data.keySet();

        String[] keyArray = keySet.toArray(new String[keySet.size()]);

        Arrays.sort(keyArray);

        StringBuilder sb = new StringBuilder();

        for (String k : keyArray) {

            if (k.equals("sign")) {

                continue;

            }

            if (data.get(k).toString().trim().length() > 0) //为空,则不参与签名

                sb.append(k).append("=").append(data.get(k).toString().trim()).append("&");

        }

        sb.append("key=").append(key);

        System.out.println(sb);

        if ("MD5".equals(signType)) {

            return MD5(sb.toString()).toUpperCase();

        }else {

            thrownew Exception(String.format("Invalid sign_type: %s", signType));

        }

}



public void getPasswordPar(){    

  String clientId=vars.get("client_id");

  String clientSecret=vars.get("client_secret");

  String username=vars.get("username");

  String password=vars.get("password");

  String salt=vars.get("salt"); 

  String grant_type=vars.get("grant_type"); 

  String passwordPar=md5AndSha(password+salt);   

  vars.put("passwordPar",passwordPar); 

  log.info("加密passwordPar begin");         

  log.info(passwordPar);

  log.info("加密passwordPar end");        

}


log.info("BeanShell 预处理程序");

/*

 * 获取加密参数passwordPar

 */

getPasswordPar();

当请求取得结果后,也可以用BeanShell 后置处理程序将请求返回做解析加工,取出想要的数据,然后存入变量供下一个请求来处理

BeanShell 后置处理程序

JMeter进阶使用变量及BeanShell 预处理程序实现复杂调试_jmeter_06

 
import com.alibaba.fastjson.JSONArray;

import com.alibaba.fastjson.JSONObject;


log.info("BeanShell 后置处理程序");


//取得请求返回结果

log.info("请求返回结果 begin");

String response = prev.getResponseDataAsString();

log.info(response); 

log.info("请求返回结果 end"); 


JSONObject json=  JSONObject.parseObject(response);

String myToken=json.getString("access_token");

//将access_token存入变量中

vars.put("myToken",myToken);

log.info("取得access_token为:"+myToken);
使用第三方库

这里后置处理程序用到fastjson库,记得下载放下JMeter库文件lib目录中

JMeter进阶使用变量及BeanShell 预处理程序实现复杂调试_BeanShell 预处理程序_07

显示调试日志

JMeter进阶使用变量及BeanShell 预处理程序实现复杂调试_BeanShell 预处理程序_08

在BeanShell 后置处理程序,还可以取得返回结果再存入变量中,如vars.put("myToken",myToken);即是将取得的access_token存入变量myToken

这里来验证

定义新一个变量myToken值默认设为myToken,看会不会有变化

JMeter进阶使用变量及BeanShell 预处理程序实现复杂调试_BeanShell 预处理程序_09

添加HTTP请求2

路径改为/getName?token=${myToken},这里路径中的${myToken}用于接收参数

JMeter进阶使用变量及BeanShell 预处理程序实现复杂调试_BeanShell 预处理程序_10

发起请求,查看HTTP请求2的返回结果,myToken确定改变了

JMeter进阶使用变量及BeanShell 预处理程序实现复杂调试_变量_11

最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】

​​​软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

在这里插入图片描述

在这里插入图片描述

<think>我们正在讨论如何使用BeanShell预处理程序实现RSA加密。根据引用[2]和引用[3]中提供的示例代码,我们可以借鉴一些思路。引用[2]展示了在JMeter使用Java代码调用RSAUtil类进行加密和签名的示例,引用[3]则展示了使用BeanShell进行AES加密的示例。我们可以结合这两个示例,编写一个使用BeanShell进行RSA加密的示例。注意:RSA加密通常需要公钥。在BeanShell中,我们可以使用Java的加密库来实现。步骤:1.导入必要的Java加密库。2.获取需要加密的数据。3.加载公钥(通常从文件、字符串或环境变量中获取)。4.使用公钥初始化RSA加密算法。5.对数据进行加密。6.通常会对加密结果进行Base64编码,以便于传输。7.将加密后的结果存储到JMeter变量中,以便后续请求使用。假设我们有一个RSA公钥字符串(PEM格式),我们需要将其转换为Java中的PublicKey对象。注意,PEM格式的公钥通常以"-----BEGINPUBLICKEY-----"开头,我们需要去除这些标记并处理Base64编码的密钥内容。由于BeanShell本质上是Java代码,我们可以使用Java的加密库(如java.security)来实现。示例代码:注意:在实际使用中,请将公钥字符串替换为实际可用的公钥。下面是一个示例代码,它使用字符串形式的公钥(PEM格式)进行RSA加密:```java//导入必要的类importorg.apache.commons.codec.binary.Base64;importjava.security.KeyFactory;importjava.security.PublicKey;importjava.security.spec.X509EncodedKeySpec;//需要加密的原始数据StringoriginalData="需要加密的数据";//公钥字符串(PEM格式,去除头尾标记和换行符)StringpublicKeyPEM="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsgO5gVYkQfZ5nT1aZ7l\n"+"...其余公钥内容...\n"+"-----ENDPUBLICKEY-----";//去除PEM格式的头尾标记和换行符StringpublicKeyBase64=publicKeyPEM.replace("-----BEGINPUBLICKEY-----","").replace("-----ENDPUBLICKEY-----","").replaceAll("\\s","");//去除所有空白字符(包括换行)//将Base64字符串解码为字节数组byte[]publicKeyBytes=Base64.decodeBase64(publicKeyBase64);//生成公钥对象PublicKeypublicKey=null;try{KeyFactorykeyFactory=KeyFactory.getInstance("RSA");X509EncodedKeySpeckeySpec=newX509EncodedKeySpec(publicKeyBytes);publicKey=keyFactory.generatePublic(keySpec);}catch(Exceptione){log.error("Failedtogeneratepublickey",e);//或者使用System.out.println输出错误System.out.println("Error:"+e.getMessage());}//使用公钥加密数据if(publicKey!=null){try{//获取RSA加密实例javax.crypto.Ciphercipher=javax.crypto.Cipher.getInstance("RSA");cipher.init(javax.crypto.Cipher.ENCRYPT_MODE,publicKey);byte[]encryptedBytes=cipher.doFinal(originalData.getBytes("UTF-8"));//对加密结果进行Base64编码StringencryptedBase64=Base64.encodeBase64String(encryptedBytes);//将加密后的字符串存储到JMeter变量中vars.put("encryptedData",encryptedBase64);System.out.println("EncryptedData(Base64):"+encryptedBase64);}catch(Exceptione){log.error("Encryptionfailed",e);System.out.println("EncryptionError:"+e.getMessage());}}else{System.out.println("Publickeyisnull,encryptionaborted.");}```说明:1.上述代码中,我们首先处理PEM格式的公钥字符串,将其转换为Java能够识别的X509EncodedKeySpec。2.然后使用KeyFactory生成公钥对象。3.使用Cipher进行加密,加密模式为RSA(实际使用中可能是RSA/ECB/PKCS1Padding,但这里使用默认的RSA,具体提供者可能有不同的默认实现。为了明确,建议指定完整的算法,例如:"RSA/ECB/PKCS1Padding")。4.加密后的字节数组通常需要Base64编码,以便作为字符串传输。注意:由于JMeterBeanShell支持日志对象(log),我们可以使用log.error记录错误,也可以使用System.out.println输出到控制台。如果公钥不是PEM格式,而是直接以Base64字符串形式存在(没有头尾标记),则无需进行替换操作。另外,如果加密的数据较长,可能需要考虑RSA加密对数据长度的限制(例如,使用RSA2048位密钥最多可以加密245字节)。对于更长的数据,通常采用对称加密(如AES)加密数据,然后用RSA加密对称密钥的方式。以上代码提供了一个基本示例,实际使用时需要根据具体环境调整。相关问题:1.如何在JMeter中生成RSA密钥对?2.如何处理RSA加密的数据长度限制?3.在JMeter中如何安全地存储和使用密钥?4.如何使用BeanShell实现RSA解密?</think>### BeanShell 实现 RSA 加密示例 在 JMeter使用 BeanShell 预处理程序实现 RSA 加密,主要步骤如下(完整代码见下方): #### 核心步骤 1. **导入加密库** 使用 Java 加密体系(JCE)的标准库: ```java import javax.crypto.Cipher; import java.security.KeyFactory; import java.security.PublicKey; import java.security.spec.X509EncodedKeySpec; import org.apache.commons.codec.binary.Base64; ``` 2. **准备公钥** 公钥需为 Base64 编码的 DER 格式(去掉 PEM 头尾标记): ```java String publicKeyBase64 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuVEX..."; // 实际公钥 byte[] publicKeyBytes = Base64.decodeBase64(publicKeyBase64); ``` 3. **生成公钥对象** 通过密钥工厂转换: ```java PublicKey publicKey = KeyFactory.getInstance("RSA") .generatePublic(new X509EncodedKeySpec(publicKeyBytes)); ``` 4. **执行加密** 使用 RSA/ECB/PKCS1Padding 模式: ```java Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8")); ``` 5. **Base64 编码结果** 将二进制结果转为可传输字符串: ```java String encryptedBase64 = Base64.encodeBase64String(encryptedBytes); ``` #### 完整 BeanShell 代码 ```java import javax.crypto.Cipher; import java.security.KeyFactory; import java.security.PublicKey; import java.security.spec.X509EncodedKeySpec; import org.apache.commons.codec.binary.Base64; // 配置参数 String plainText = "需要加密的数据"; // 待加密内容 String publicKeyPEM = "-----BEGIN PUBLIC KEY-----\n" + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuVEX...\n" // 实际公钥 + "-----END PUBLIC KEY-----"; // 处理PEM格式公钥(移除头尾标记和换行符) String publicKeyBase64 = publicKeyPEM .replace("-----BEGIN PUBLIC KEY-----", "") .replace("-----END PUBLIC KEY-----", "") .replaceAll("\\s", ""); // 生成公钥对象 byte[] publicKeyBytes = Base64.decodeBase64(publicKeyBase64); PublicKey publicKey = KeyFactory.getInstance("RSA") .generatePublic(new X509EncodedKeySpec(publicKeyBytes)); // RSA加密 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8")); // Base64编码结果 String encryptedBase64 = Base64.encodeBase64String(encryptedBytes); // 存储到JMeter变量 vars.put("encryptedData", encryptedBase64); log.info("加密结果: " + encryptedBase64); ``` #### 关键说明 1. **公钥格式要求** - 必须使用 PKCS#8 标准的 DER 编码格式 - 在代码中需移除 PEM 头尾标记 `-----BEGIN/END PUBLIC KEY-----` 和换行符 2. **加密模式** `RSA/ECB/PKCS1Padding` 是行业标准方案,确保与多数系统兼容[^2] 3. **数据长度限制** RSA 加密有最大长度限制(例如 2048 位密钥最多加密 245 字节),超长数据需分段处理或改用混合加密(如 RSA+AES)[^3] 4. **依赖库** - `Base64` 依赖 `commons-codec.jar`,需放入 JMeter 的 `lib` 目录 - JMeter 5.4+ 已内置该库 5. **调试建议** 使用 `log.info()` 输出中间结果,或通过 `View Results Tree` 查看调试信息 > **注**:实际使用时需替换 `publicKeyPEM` 为有效的公钥,并根据业务需求调整加密内容[^1]。 --- ### 相关问题 1. 如何在 JMeter 中生成 RSA 密钥对? 2. BeanShell 实现 RSA 解密有哪些注意事项? 3. 如何处理 RSA 加密的数据长度限制问题? 4. JMeter 中如何安全地存储加密密钥? 5. 除了 BeanShellJMeter 还有哪些组件可实现加密操作? [^1]: 引用自 RSA 加密原理及实现规范 [^2]: 参考 Java 加密体系标准 (JCE) 文档 [^3]: 数据加密长度限制解决方案,参见 PKCS#1 标准文档
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值