在金融领域,牵涉到下单支付的接口,为了增加接口的安全性(防止中间人攻击),增加md5签名算法。分别用java和javaScript实现,测试签名结果一致,大家可以放心使用。
md5验签算法主要有以下几步:
1,将请求头head和请求体body合并, 并剔除key值为sign的选项,因为签名本身不参与计算;
2,将参数名key按照ASCII码从小到大排序(字典序),参数名区分大小写;
3,如果key或者value的值为null或者空字符串则不参与签名;
4,将签名密钥和待签名字符串一起进行md5算法计算,得到签名sign值
java实现
HashMap<String, String> params = new HashMap<String, String>();
HashMap<String, String> head = new HashMap<String, String>();
head.put("trans_code", "0001");
head.put("chnlId", "01");
head.put("chnlUserId", "da91d3a936f34fad82788892c4574e43b");
head.put("sessionId", "4cfjejenddu1fcd4b6eaa4f8db4fe628a8a");
head.put("timestamp", System.currentTimeMillis());
HashMap<String, String> body = new HashMap<String, String>();
body.put("bakNo", "77777777777");
body.put("productNo", "66666666666");
body.put("accountNum", 3);
body.put("moduleType", "1");
String sign = NetUtils.getSign(head, body); // 进行签名计算
head.put("sign", "'" + sign + "'");
params.put("syshead", head.toString());
params.put("body", body.toString());
String msgId = "0001";
String url = "";
net.execute(url, params, new NetMessage(msgId));
NetUtils.java
public class NetUtils {
public static String getSign(HashMap<String, String> head, HashMap<String, String> body) {
HashMap<String, String> signMap = new HashMap<String, String>();
signMap.putAll(body);
signMap.putAll(head);//head中的参数覆盖body
signMap.remove("sign");
return getSign(signMap);
}
public static String getSign(HashMap<String, String> requestParams) {
List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>
(requestParams.entrySet());
// 对HashMap中的key 进行排序
Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
return (o1.getKey()).toString().compareTo(o2.getKey().toString());
}
});
StringBuilder paramsBuilder = new StringBuilder("");
for (int i = 0; i < infoIds.size(); i++) {
String key = infoIds.get(i).getKey();
String value = infoIds.get(i).getValue();
if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value) || "''".equals(value) || "'null'".equals(value)) {
continue;
}
paramsBuilder.append(key + value);
}
//验证密钥
String confirmKey = "";
//md5计算,原map中value大多加了单引号,需要去除
String md1 = getMD5(confirmKey + paramsBuilder.toString().replaceAll("'", ""));
if (md1 != null) {
String md2 = getMD5(md1.substring(0, 5) + md1.substring(md1.length() - 5, md1.length()));
return md2.toUpperCase();//转大写
}
return "";
}
public static String getMD5(String data) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("MD5");
md.update(data.getBytes());
byte byteData[] = md.digest();
StringBuffer result = new StringBuffer();
for (int i = 0; i < byteData.length; i++) {
result.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
}
return result.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
}
javaScript实现
安装md5:
npm install md5 --save
import md5 from 'md5';
var data = {
"syshead": {
"trans_code": '0001',
"chnlId": '01',
"chnlUserId": 'da91d3a936f34fad82788892c4574e43b',
"sessionId": '4cfjejenddu1fcd4b6eaa4f8db4fe628a8a',
"timestamp": new Date().getTime()
},
"body": {
"bakNo": '77777777777',
"productNo": '66666666666',
"accountNum": 3,
"moduleType": '1'
}
}
data.syshead.sign = me.getSign(data.syshead, data.body);
获取md5签名
getSign(syshead, body) {
let signObj = {};
Object.assign(signObj, syshead, body);
delete signObj.sign;
function getSignString(params) {
let arr = [];
for (let key in params) {
if (!key || !params[key]) {
continue;
}
arr.push(key + params[key]);
}
return arr.sort().join('').replace(/\'/g, "");
}
let sign = getSignString(signObj); //获取签名字符串sign
//验证密钥
let confirmKey = '';
//md5计算
let md1 = md5(confirmKey + sign);
if (md1) {
let md2 = md5(md1.substring(0, 5) + md1.substring(md1.length - 5, md1.length));
return md2.toUpperCase();//转大写
}
return "";
}