You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JMeter JSR223脚本报错求助:SHA256+AES加密脚本问题

JMeter JSR223脚本错误排查与修正

问题背景

在JMeter登录测试中,需对CSV读取的密码先执行SHA256哈希,再进行AES加密(目标系统采用前端SHA256+AES的安全机制)。运行JSR223 PreProcessor脚本时触发javax.script.ScriptException,错误指向第17行的String.format方法调用,提示找不到对应静态方法。

错误脚本

import java.security.MessageDigest;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

String plaintextPassword = vars.get("PASSWORD");

try {
    // Step 1: SHA-256 Hashing
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    md.update(plaintextPassword.getBytes());
    byte[] digest = md.digest();

    StringBuilder sha256Hash = new StringBuilder();
    for (byte b : digest) {
        sha256Hash.append(String.format("%02x", b)); // 第17行,报错行
    }

    String _Key = "____"; // 需替换为实际Base64编码的密钥

    // Step 2: AES Encryption
    Cipher _Cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
  
    // 从Base64编码的密钥生成SecretKeySpec
    SecretKeySpec secretKey = new SecretKeySpec(Base64.decodeBase64(_Key), "AES");

    _Cipher.init(Cipher.ENCRYPT_MODE, secretKey);

    byte[] encryptedBytes = _Cipher.doFinal(sha256Hash.toString().getBytes());

    // 将加密后的字节转换为Base64编码字符串
    String encryptedPassword = Base64.encodeBase64String(encryptedBytes);

    vars.put("encryptedPassword", encryptedPassword);

} catch (Exception e) {
    log.error("Error occurred: " + e.getMessage());
    throw new RuntimeException(e);
}

错误日志

ERROR o.a.j.m.JSR223PreProcessor: Problem in JSR223 script, JSR223 PreProcessor
javax.script.ScriptException: Sourced file: inline evaluation of: ``import java.security.MessageDigest; import javax.crypto.Cipher; import javax.cry . . . '' : Error in method invocation: Static method format( java.lang.String, byte ) not found in class'java.lang.String' : at Line: 17 : in file: inline evaluation of: ``import java.security.MessageDigest; import javax.crypto.Cipher; import javax.cry . . . '' : String .format ( "%02x" , b ) 
 in inline evaluation of: ``import java.security.MessageDigest; import javax.crypto.Cipher; import javax.cry . . . '' at line number 17
    at bsh.engine.BshScriptEngine.evalSource(BshScriptEngine.java:93) ~[bsh-2.0b6.jar:2.0b6 2016-02-05 05:16:19]
    at bsh.engine.BshScriptEngine.eval(BshScriptEngine.java:46) ~[bsh-2.0b6.jar:2.0b6 2016-02-05 05:16:19]
    at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:231) ~[java.scripting:?]
    at org.apache.jmeter.util.JSR223TestElement.processFileOrScript(JSR223TestElement.java:232) ~[ApacheJMeter_core.jar:5.6.2]
    at org.apache.jmeter.modifiers.JSR223PreProcessor.process(JSR223PreProcessor.java:45) ~[ApacheJMeter_components.jar:5.6.2]
    at org.apache.jmeter.threads.JMeterThread.runPreProcessors(JMeterThread.java:983) ~[ApacheJMeter_core.jar:5.6.2]
    at org.apache.jmeter.threads.JMeterThread.executeSamplePackage(JMeterThread.java:561) ~[ApacheJMeter_core.jar:5.6.2]
    at org.apache.jmeter.threads.JMeterThread.processSampler(JMeterThread.java:501) ~[ApacheJMeter_core.jar:5.6.2]
    at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:268) ~[ApacheJMeter_core.jar:5.6.2]
    at java.lang.Thread.run(Thread.java:1623) [?:?] 

问题分析

  1. String.format参数兼容问题:BeanShell引擎无法识别String.format("%02x", byte)的方法签名,因为byte是有符号类型,需转换为无符号int(通过b & 0xFF)才能正确格式化。
  2. AES CBC模式缺失IV:脚本使用AES/CBC/PKCS5Padding模式,但未指定初始化向量(IV),CBC模式必须依赖IV才能完成加密初始化,否则会触发异常。

修正后的脚本

import java.security.MessageDigest;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import org.apache.commons.codec.binary.Base64;

String plaintextPassword = vars.get("PASSWORD");
// 替换为与目标系统一致的Base64编码密钥和IV
String aesKeyBase64 = "你的Base64编码密钥";
String ivBase64 = "你的Base64编码IV";

try {
    // Step 1: SHA-256哈希(指定UTF-8编码,与前端保持一致)
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    md.update(plaintextPassword.getBytes("UTF-8"));
    byte[] digest = md.digest();

    StringBuilder sha256Hash = new StringBuilder();
    for (byte b : digest) {
        // 将byte转换为无符号int,解决BeanShell兼容问题
        sha256Hash.append(String.format("%02x", b & 0xFF));
    }

    // Step 2: AES CBC加密
    // 解码Base64格式的密钥和IV
    byte[] keyBytes = Base64.decodeBase64(aesKeyBase64);
    byte[] ivBytes = Base64.decodeBase64(ivBase64);

    SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
    IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);

    // 对SHA256哈希结果加密(指定UTF-8编码)
    byte[] encryptedBytes = cipher.doFinal(sha256Hash.toString().getBytes("UTF-8"));

    // 加密结果转换为Base64字符串
    String encryptedPassword = Base64.encodeBase64String(encryptedBytes);

    vars.put("encryptedPassword", encryptedPassword);

} catch (Exception e) {
    log.error("加密处理失败: " + e.getMessage(), e); // 打印完整堆栈便于排查
    throw new RuntimeException(e);
}

额外注意事项

  • 脚本引擎选择:优先使用Groovy引擎而非BeanShell,Groovy性能更高且对Java语法支持更完善,可避免此类兼容问题。在JSR223元件的语言下拉框中选择groovy即可。
  • 密钥与IV一致性:必须确保密钥、IV的编码格式(Base64)和值与目标系统前端完全一致,否则加密结果不匹配。
  • 字符编码:所有字节转换操作指定UTF-8编码,避免因默认编码差异导致哈希/加密结果错误。

内容的提问来源于stack exchange,提问作者mrvnrfm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 06:07:04