背景
明文传输是不安全的,使用MD5加密是个简单易行的方式。
大致介绍
用户注册后,生成key和secret,用户和后端都持有。用户在发送数据时,将数据以及secret加在一起求MD5,在发送时附带一个sign,sign的值即为刚刚求的MD5值,后端接受到请求后,使用同样的方式求sign,对比是否一致,从而验证身份
代码实现
public class SignUtil {
public static String sign(String secret, Command command) throws IllegalAccessException {
Map<String, Object> signMap = new HashMap<>();
Map<String, Object> bodyMap = getBodyParams(command);
if (bodyMap != null) {
signMap.putAll(bodyMap);
}
StringBuffer sb = new StringBuffer();
signMap.forEach((k, v) -> {
sb.append(k).append("=").append(v).append("&");
});
sb.append("secret=").append(secret);
// System.out.println("string : " + sb.toString());
return stringToMD5(sb.toString());
}
private static <T> Map<String, Object> getBodyParams(T body) throws IllegalAccessException {
if (body == null) {
return null;
}
Map<String, Object> bodyMap = new HashMap<>();
for (Field field : body.getClass().getDeclaredFields()) {
field.setAccessible(true);
bodyMap.put(field.getName(), field.get(body));
}
return bodyMap;
}
public static String stringToMD5(String plainText) {
byte[] secretBytes = null;
try {
secretBytes = MessageDigest.getInstance("md5").digest(
plainText.getBytes());
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException();
}
return new BigInteger(1, secretBytes).toString(16);
}
}
其中command为请求体,即requestbody。所有属性按字典序排序后,求MD5值。
小技巧
使用python快速求MD5值,免的写代码的时候需要一个MD5值,java项目启动慢。
参考如下示例
import hashlib
string = "contentType=text&key=test-1656927918300&content=今日没雨,不用带伞&secret=990f53b4cdd3f8f556e2c281ca67de27"
print(hashlib.md5((string).encode('utf-8')).hexdigest())