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等特殊字符,需要替換掉。