public class SignatureUtil {
private static final String CHARSET = "UTF-8";
private static final String SIGN_TYPE = "MD5";
/**
* 判斷簽名是否正确,必須包含sign字段,否則傳回false。
*
* @param data Map類型資料
* @param key API密鑰
* @return 簽名是否正确
* @throws Exception
*/
public static boolean check(Map<String, String> data, String key, String signField){
if (!data.containsKey(signField)) {
return false;
}
String sign = data.get(signField);
return sign(data, key, signField).equals(sign);
}
/**
* 生成簽名. 注意,若含有sign_type字段,必須和signType參數保持一緻。
*
* @param data 待簽名資料
* @param key API密鑰
* @return 簽名
*/
public static String sign(final Map<String, String> data, String key, String signField) {
Set<String> keySet = data.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for (String k : keyArray) {
if (k.equals(signField)) {
continue;
}
// 參數值為空,則不參與簽名
if (data.get(k).trim().length() > 0) {
sb.append(k).append("=").append(data.get(k).trim()).append("&");
}
}
sb.append("key=").append(key);
System.out.println("驗簽封裝的串為:"+sb);
String result=MD5(sb.toString()).toUpperCase();
System.out.println("生成的簽名為:"+result);
return result;
}
/**
* 生成 MD5
*
* @param data 待處理資料
* @return MD5結果
*/
private static String MD5(String data) {
try {
MessageDigest md = MessageDigest.getInstance(SIGN_TYPE);
byte[] array = md.digest(data.getBytes(CHARSET));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toUpperCase();
}
catch (Exception e){
throw new RuntimeException(e);
}
}
}
上面的簽名工具類,下面是示例。
驗簽示例:
Map<String, String> params = new TreeMap<>();
params.put("channel", commonRequest.getChannel());
params.put("data", commonRequest.getData());
params.put("sign", commonRequest.getSign());
//檢查簽名
SignatureUtil.check(params, signKey, "sign");
生成簽名示例:
Map<String, String> map = new HashMap<>();
map.put("channel", "app");
map.put("data", DESUtil.Des3EncodeCBC(desKey, JSON.toJSONString(request)).replaceAll("\r\n|\r|\n|\n\r", ""));
String sign = SignatureUtil.sign(map, signKey, "sign");
map.put("sign", sign);
注意:進行DES加密時,加密後的字元串裡包含\n等特殊字元,需要替換掉。