Jmeter使用beanshell对数据进行加密传输

Posted 往事如云烟都付笑谈中

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jmeter使用beanshell对数据进行加密传输相关的知识,希望对你有一定的参考价值。

首先,来看一下接口签名加密规则

1.需要参于签名的参数:

	a. 在请求参数列表中,除去 cliSign 参数外,其他需要使用到的参数皆是要签名的参数。
	
2.生成签名字符串

	a.	没有值的参数无需传递,也无需包含到待签名数据中
	
	b.	签名数据应该是原生值而不是 encoding 之后的值
	
	c.	若遇参数值为数组时,请以char=7对应字符进行分割此参数的多个值
	
	d. 按签名参数 a 到 z 的顺序排序("&"是分割开出多个参数)
	
		签名参数字符串如下:
		
		params = channel =0&password=abc&userid=13876
		
		pass = md5(params + appkey).toLowerCase() 注:“+”加与为字符串相连符,不在签名字符里,appkey为秘钥,为双方平台约定字符

		加密后cliSign = pass.substring(5, 21);全部小写后,获取前8到24位共16位传到服务端;

		
	e.  针对部分CDN接口若有传中文,客户端请在对中文URLEncoder后加密
	
3.开发测试环境签名密钥:

	appkey="test888"

beanshell代码如下:

import org.apache.commons.codec.digest.DigestUtils; 

//业务字段
String accessToken = vars.get("access_token");
String userId = vars.get("user_id");
String videoId = vars.get("videoId");

//POST/get请求公共参数
String appId = vars.get("appId");
String brand = vars.get("brand");
String channel = vars.get("channel");
String device = vars.get("device");
String platform = vars.get("platform");
String sysVersion = vars.get("sysVersion");
String times = vars.get("times");
String version = vars.get("version");
String appkey = vars.get("appkey");

//将签名传给cliSign参数,使用treemap,可自动进行排序
Map map = new TreeMap();

map.put("accessToken", accessToken);
map.put("userId", userId);
map.put("videoId", videoId);

map.put("appId", appId);
map.put("brand", brand);
map.put("channel", channel);
map.put("device", device);
map.put("platform", platform);
map.put("sysVersion", sysVersion);
map.put("times",times);
map.put("version", version);

//URLEncoder.encode(value, "UTF-8")   对中文进行格式化,这里不需要  

StringBuffer sb = new StringBuffer();
for (Map.Entry entry : map.entrySet()) {
	sb.append(entry.getKey() + "=" + entry.getValue());
	sb.append("&");
	}
	String s = sb.toString();
	if (s.endsWith("&")) {
		s = org.apache.commons.lang.StringUtils.substringBeforeLast(s, "&");
	}
	log.info("Map转换为URL编码"+s);

String str1 = s+appkey;
log.info("待加密字符串为:"+str1);
//进行md5加密
String pass = DigestUtils.md5Hex(str1).toLowerCase();
log.info("加密后的值:"+pass);
//截取前8到21位为签名
String sign = pass.substring(5, 21);
log.info("最终签名为:"+sign);
//将签名传给cliSign参数
vars.put("cliSign",sign);


技巧总结

  1. 将可能发生变动的参数均进行参数化,然后使用vars.put()方法获取,这样以后就不需要再修改beanshell中的代码
  2. 由于每个接口都需要用一个beanshell来获取签名,最好将业务参数和公共参数分开,便于修改和查看
  3. 对于关键变量,将其打印到日志中,方便定位问题,比如我之前碰到的问题:
    a. 不确定拼接后的参数是否正确、顺序是否正确,是否需要用URLEncoder进行转码或者获取参数时出错等,只有打印出来后才能知道;
    b.不确定加密后的值是否正确,有可能与开发使用的加密方法不一致;
    c. 不确定截取后,最终签名是否正确
    签名机制就是这样,每一步都不能出错,需要步步为营,抽丝剥茧。找到是哪一步出的问题

附录:URL在线转码测试

本次的坑

  1. 从csv文件中读取的参数,自动加上了“”,导致最终传参不正确(在csv文件配置中将【是否允许带引号】设置为true即可);
  2. 对参数进行了URLEncoder转码,后来发现不需要;
  3. 能复制就不要手写,有的时候参数名就错了一个字母,但是找起来真的很头疼;
  4. 如果可以,最好找开发用一个实际的接口进行详细的示例,只看文档会跑偏。

以上是关于Jmeter使用beanshell对数据进行加密传输的主要内容,如果未能解决你的问题,请参考以下文章

JMeter常用脚本开发之BeanShell PreProcessor

jmeter beanshell里面写了函数怎么调用

JMeter基础 — JMeter中BeanShell断言详解

jmeter BeanShell实例-----两个变量之间的断言对比

jmeter之beanshell断言---数据处理

jmeter,BeanShell PreProcessor简单使用引入jmeter参数