接口请求中的签名 signature,是一串加密后的字符串,作为请求体的一个参数放在 Request 中。
对接口中传递的参数进行加密,需要以密文的形式发送出去。
一、JMeter 中 BeanShell PreProcessor 进行编写验签方法,代码如下:
public class SignTest{
public static String getSignature(Map params,String Key) {
Map sortedParams = new TreeMap(params);
//先将这些请求参数以其参数名的字典序升序进行排序
Set entrys = sortedParams.entrySet();
// 遍历排序后的字典,将所有参数按""key=value""格式拼接在一起
StringBuilder basestring = new StringBuilder();
for (Entry param : entrys) {
String key = param.getKey();
String value = param.getValue();
if(value == null){
value = "";
}
basestring.append(key).append("=").append(value);
}
basestring.append(Key);
//log.info("Sign Source:" + basestring);
// 使用 MD5 对待签名串求签
byte[] bytes = null;
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
bytes = md5.digest(basestring.toString().getBytes("UTF-8"));
} catch (Exception ex) {
log.error("getSignature:" + params.toString(), ex);
}
###
// 将 MD5 输出的二进制结果转换为小写的十六进制
StringBuilder sign = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() == 1) {
sign.append("0");
}
sign.append(hex);
}
return sign.toString();
}
public static void addSignture(){
Arguments arguments = sampler.getArguments();
Map inMap = new HashMap();
int len=arguments.getArgumentCount();
for(int i=0;i<len;i++){
Argument jpro=arguments.getArgument(i);
String key=jpro.getName();
String ret=jpro.getValue();
inMap.put(key,ret);
}
String key= vars.get("Key");
String signresult=getSignature(inMap,key);
arguments.addArgument(new HTTPArgument("sign",signresult));
}
}
SignTest.addSignture();
二、JMeter 中 BeanShell PreProcessor 进行证书加密及解密的方法,代码如下:
加密:
String keySecret = "${appKey}";//secret
String encryptSignKey = "weiyankeji.cn";//加签 key
String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDARhN2p7W6qaR73dpgpr9vo";
log.info("\n\n===============start to encryt the params,"+vars.getClass());
try{
Map paramsTemp = new HashMap();
Map params = new HashMap();
Arguments arguments = sampler.getArguments();
int i = arguments.getArgumentCount();
for(int j=0;j<i;j++){
HTTPArgument arg = arguments.getArgument(j);
params.put(arg.getName(),arg.getValue());
}
String sign = Signature.sign(params, keySecret);
log.info("\n\n===============print the sign,"+sign);
params.put("sign", sign);
String paramsJson = JSON.toJSONString(params);
System.out.println("=====================paramsJson=======================");
System.out.println(paramsJson);
log.info("\n\n===============print the params,"+paramsJson);
byte[] encryptData = RSAUtils.encryptByPublicKey(paramsJson.getBytes(Charsets.UTF_8), publicKey.getBytes());
log.info("\n\n===============print the params,"+paramsJson);
paramsTemp.put("Id", "${Id}");
paramsTemp.put("timestamp", "${timestamp}");
paramsTemp.put("encryptType", "rsa");
paramsTemp.put("encrypt", new String(Base64Utils.encode(encryptData)));
String msgSignature = Signature.sign(paramsTemp, encryptSignKey);
paramsTemp.put("msgSignature", msgSignature);
log.info("\n\n=============== finished the paramstemp="+JSON.toJSONString(paramsTemp));
arguments.removeAllArguments();
for(Entry entry :paramsTemp.entrySet()){
arguments.addArgument(new HTTPArgument(entry.getKey(), entry.getValue()));
}
}
catch(Throwable ex){
log.error("===============Error in Beanshell", ex);
throw ex;
}
解密:
String sinatureKey = "wsdjljksfs";
log.info("\n\n===============start to decrypt the params,"+prev.getClass());
String result = prev.getResponseDataAsString();
String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKFGnds0H";
JSONObject responseObj = JSON.parseObject(result);
Map responseParams = Maps.newHashMap();
for (Map.Entry entry : responseObj.entrySet()) {
responseParams.put(entry.getKey(), String.valueOf(entry.getValue()));
}
responseParams.remove("msgSign");
String responseGenSign = Signature.sign(responseParams, sinatureKey);
log.info("\n\n===============sign to decrypt the params,"+responseGenSign);
if(! responseGenSign.equals(responseObj.getString("msgSign"))){
log.info("\n\n=============== sign failure=============================");
return;
}
log.info("\n\n===============start to decrypt the params,"+responseObj);
String responseEncrypt = responseObj.getString("encrypt");
byte[] decryptData = RSAUtils.decryptByPrivateKey(
Base64Utils.decode(responseEncrypt.getBytes(Charsets.UTF_8)),
privateKey.getBytes());
System.out.println("=====================response decrypt=======================");
System.out.println(new String(decryptData, Charsets.UTF_8));
log.info("\n\n===============end to decrypt the params,"+new String(decryptData, Charsets.UTF_8));
prev.setResponseData(new String(decryptData, Charsets.UTF_8));
↙↙↙阅读原文可查看相关链接,并与作者交流