如何在JMeter、LoadRunner等性能测试工具中处理TOTP认证?
在JMeter和LoadRunner中处理AWS TOTP认证的方案
绝对可以搞定!不管是JMeter还是LoadRunner,都有成熟的办法处理AWS TOTP认证的流程,我给你一步步拆解具体怎么做:
在JMeter中处理AWS TOTP认证
JMeter通过自定义脚本就能轻松生成符合AWS标准的TOTP令牌,核心思路是用Groovy编写TOTP生成逻辑,步骤如下:
- 先确认你拿到的AWS MFA密钥是Base32格式的(就是配置MFA时显示的那个字符串,可能带空格,记得去掉)。
- 添加一个JSR223 Sampler到你的测试计划里,放在用户名密码登录请求之后、TOTP输入请求之前。选择Groovy作为脚本语言,因为它性能比其他脚本语言好。
- 把下面的代码复制进去,替换
secretKey的值为你的AWS MFA密钥:import org.apache.commons.codec.binary.Base32 import javax.crypto.Mac import javax.crypto.spec.SecretKeySpec String secretKey = "你的AWS MFA Base32密钥(去掉空格)" long time = System.currentTimeMillis() / 1000 long timeWindow = time / 30 // AWS TOTP每30秒更新一次 // 解码Base32格式的密钥 Base32 base32 = new Base32() byte[] decodedKey = base32.decode(secretKey) // 初始化HMAC-SHA1算法 SecretKeySpec signKey = new SecretKeySpec(decodedKey, "HmacSHA1") Mac mac = Mac.getInstance("HmacSHA1") mac.init(signKey) // 把时间窗口转换成8字节的大端数据 byte[] data = new byte[8] for (int i = 7; i >= 0; i--) { data[i] = (byte)(timeWindow & 0xFF) timeWindow >>= 8 } // 计算哈希值并提取6位令牌 byte[] hash = mac.doFinal(data) int offset = hash[hash.length - 1] & 0x0F int binary = ((hash[offset] & 0x7F) << 24) | ((hash[offset + 1] & 0xFF) << 16) | ((hash[offset + 2] & 0xFF) << 8) | (hash[offset + 3] & 0xFF) String totp = String.format("%06d", binary % 1000000) // 把生成的令牌存到JMeter变量,后续请求用${AWS_TOTP}引用 vars.put("AWS_TOTP", totp) - 在需要输入TOTP的请求参数里,把原来的静态令牌替换成
${AWS_TOTP}即可。 - 小提示:新版本JMeter自带Apache Commons Codec包,不用额外下载;如果是老版本,需要把
commons-codec-x.x.jar放到JMeter的lib目录下重启。
在LoadRunner中处理AWS TOTP认证
LoadRunner用C语言脚本实现,需要自己处理Base32解码和HMAC-SHA1计算,步骤如下:
- 先准备Base32解码的自定义函数(因为LoadRunner没有内置这个功能),你可以找符合RFC 4648标准的Base32解码实现,或者自己写一个简单的版本。
- 在脚本中添加自定义的TOTP生成逻辑,放在登录请求之后、TOTP输入请求之前:
// 假设你已经实现了base32_decode和hmac_sha1函数 char* secret_key = "你的AWS MFA Base32密钥(去掉空格)"; byte decoded_key[20]; // AWS MFA密钥是160位,即20字节 int decoded_len = base32_decode(secret_key, decoded_key, sizeof(decoded_key)); // 计算当前时间窗口(每30秒一个周期) time_t current_time = time(NULL); long long time_window = current_time / 30; byte time_bytes[8]; // 转换为大端字节序 for (int i = 7; i >= 0; i--) { time_bytes[i] = time_window & 0xFF; time_window >>= 8; } // 计算HMAC-SHA1哈希 byte hash[20]; hmac_sha1(decoded_key, decoded_len, time_bytes, 8, hash); // 提取6位TOTP令牌 int offset = hash[19] & 0x0F; int binary = ((hash[offset] & 0x7F) << 24) | ((hash[offset+1] & 0xFF) << 16) | ((hash[offset+2] & 0xFF) << 8) | (hash[offset+3] & 0xFF); char totp[7]; sprintf(totp, "%06d", binary % 1000000); // 保存到LoadRunner参数,后续用{AWS_TOTP}引用 lr_save_string(totp, "AWS_TOTP"); - 找到录制脚本中输入TOTP的参数位置,把硬编码的值替换成
{AWS_TOTP}。 - 小提示:如果不想自己写HMAC-SHA1,也可以用LoadRunner的
web_crypt函数结合自定义逻辑,但直接写C函数更灵活。
通用注意事项
- 时间同步很关键:AWS TOTP基于时间窗口生成,测试机器的时间必须和AWS服务器时间同步(偏差不能超过30秒),否则生成的令牌无效。建议开启NTP时间同步。
- 分布式测试要统一时间:如果用JMeter分布式或者LoadRunner多负载机,所有节点的时间必须完全一致,不然每个节点生成的TOTP会不一样。
- 密钥格式要正确:确保你的AWS MFA密钥是纯Base32字符串,去掉所有空格和多余字符。
内容的提问来源于stack exchange,提问作者ciitronian
相关产品推荐
相关产品推荐

