项目场景:
系统在提供接口给第三方系统使用时,通常为了安全性会做接口加密。
设计原则:使用HTTPS安全协议 或 传输内容使用非对称加密,这里采用后者。
问题描述:
在对参数进行加密,生成sign时,相同的参数两次加密的结果不一样。
加密规则:
public class SignUtil {
/**
* Md5加密方式生成sign
* 参数名ASCII码从小到大排序(字典序)
*
* @param parameters 参数名-值
* @param secretKey 秘钥
* @return sign 签名
*/
public static String createSign(SortedMap<String, Object> parameters, String secretKey) {
StringBuffer sb = new StringBuffer();
// 所有参与传参的参数按照ASCLL排序(升序)
Set es = parameters.entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
Object v = entry.getValue();
// 字符拼接
if (null != v && !StringUtils.EMPTY.equals(v) && !"signature".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
// 末尾拼接密钥
String md5 = sb.append(secretKey).toString();
return MD5(md5).toUpperCase();
}
/**
* MD5加密
*
* @param content
* @return
*/
public static final String MD5(String content) {
char[] md5String = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
try {
byte[] btInput = content.getBytes();
MessageDigest mdInst = MessageDigest.getInstance("MD5");
mdInst.update(btInput);
byte[] md = mdInst.digest();
int j = md.length;
char[] str = new char[j * 2];
int k = 0;
for (int i = 0; i < j; ++i) {
byte byte0 = md[i];
str[k++] = md5String[byte0 >>> 4 & 15];
str[k++] = md5String[byte0 & 15];
}
return new String(str);
} catch (Exception var10) {
return null;
}
}
}
原因分析及解决方案:
1.拼接出来的字符串不一致
测试时,在加密前将要加密的字符串打印出来比较,发现两次字符串一致。
2.编码问题
加密时,两次的默认编码不一致。
在上述加上默认编码:byte[] btInput = content.getBytes("utf-8");
,问题解决。
接口验签流程
简单实现:
1.接口调用方和接口提供方约定好统一的参数加密算法。
2.接口调用方在调用时把加密后的signature放在参数中去请求接口。
3.判断时间戳有效期。
4.将参数用约定号的加密算法进行加密,与参数中的signature进行比较,一致则调用接口。
// 签名密钥
String secretKey = PropertiesUtil.getProperties("api.properties", "secretKey");
// 生成签名
Map params = JSONObject.parseObject(jsonStr, Map.class);
SortedMap<String, Object> temps = new TreeMap<>();
temps.putAll(params);
String sign = SignUtil.createSign(temps, secretKey);
// 签名验证
if (!signature.equals(sign)) {
return "签名不一致!";
}
return service.getInfo(param1, param2);
创作不易,关注、点赞就是对作者最大的鼓励,欢迎在下方评论留言
求关注,定期分享Java知识,一起学习,共同成长。
网友评论