import java.security.MessageDigest; import java.util.Arrays; import java.util.Map; import org.springframework.util.StringUtils; public class SignUtil { public static String signTopRequest(Map<String, Object> params, String secret) throws Exception{ // 第一步:检查参数是否已经排序 String[] keys = params.keySet().toArray(new String[0]); Arrays.sort(keys); // 第二步:把所有参数名和参数值串在一起 StringBuilder query = new StringBuilder(); for (String key : keys) { String value = replaceNullStr(params.get(key)); if (!StringUtils.isEmpty(key)&&!StringUtils.isEmpty(value)) { if("sign".equals(key)){ continue; } query.append(key).append(CONST.CONNECT_EQUAL).append(value).append(CONST.CONNECT_AND); } } String strtemp = null; if(query.length()>0){ strtemp = query.substring(0, query.lastIndexOf(CONST.CONNECT_AND)); } // 第三步:使用MD5加密 byte[] bytes; strtemp = strtemp + secret; System.out.println(strtemp); bytes = encryptMD5(strtemp); // 第四步:把二进制转化为大写的十六进制 // return new String(bytes,"UTF-8"); return byte2hex(bytes); } private static String replaceNullStr(Object str) { if(str == null){ return ""; } return str.toString(); } /** * 加密 * @param data * @return */ private static byte[] encryptMD5(String data) throws Exception { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(data.getBytes("UTF-8")); return md.digest(); } /** * 二进制转化为大写的十六进制 * @param bytes * @return */ public static String byte2hex(byte[] bytes) { StringBuilder sign = new StringBuilder(); for (int i = 0; i < bytes.length; i++) { String hex = Integer.toHexString(bytes[i] & 0xFF); if (hex.length() == 1) { sign.append("0"); } sign.append(hex.toUpperCase()); } return sign.toString(); } }
import org.apache.commons.codec.digest.DigestUtils; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class Test { public static void main(String args[]) throws NoSuchAlgorithmException, UnsupportedEncodingException { String str = "brand_id=MB1000000000001&scene_str=ddsd..."; String sign1 = DigestUtils.md5Hex(str); System.out.println("第一次md5加密的字符串是"); System.out.println("第一次md5加密后转大写的"); System.out.println(sign1); System.out.println(sign1.toUpperCase()); MessageDigest md = MessageDigest.getInstance("MD5"); md.update(sign1.getBytes("UTF-8")); byte[] bytes = md.digest(); //encryptMD5(strtemp); /** * 二进制转化为大写的十六进制 * @param bytes * @return */ StringBuilder sign = new StringBuilder(); for (int i = 0; i < bytes.length; i++) { String hex = Integer.toHexString(bytes[i] & 0xFF); if (hex.length() == 1) { sign.append("0"); } sign.append(hex.toUpperCase()); } String result = sign.toString(); System.out.println(result); } }
在请求参数列表中,除去sign参数外,其他需要使用到的参数(参数值为空或空字符串除外)皆是要签名的参数。
例如下的签名参数:
brand_id=MB1000000000001
scene_str=card_center
timestamp=1504688298167
user_id=ksXMQfCgMAPT5GhKuGoTJTeFN7rxYDUdQNmfIfTUWtnGbg+IZPYBarluhEZKR1wYJS2h4odHkXhusDb49ysYbleBXH2ScnfmP9GfWVs9lKXgZXqFzkdPqxhLN3fmIV/cx3l4DCMsCHy5dmrZLmufPeUnNY/IIYG8k6+vVd3DiEc=
签名秘钥:
sign_key=”xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”
将所有参与签名的参数名按照字典排序(每一个参数名按照a-z的顺序排序),若遇到相同的首字母,则看第二个字母,以此类推。排序完成后,再把数组所有参数按照“参数=参数值用”的模式用“&”字符拼接成字符串,并在得到的字符串最后拼接上签名秘钥sign_key得到待签名字符串signTempStr。
signTempStr=“brand_id=MB1000000000001&scene_str=card_center×tamp=1504688298167&user_id=ksXMQfCgMAPT5GhKuGoTJTeFN7rxYDUdQNmfIfTUWtnGbg+IZPYBarluhEZKR1wYJS2h4odHkXhusDb49ysYbleBXH2ScnfmP9GfWVs9lKXgZXqFzkdPqxhLN3fmIV/cx3l4DCMsCHy5dmrZLmufPeUnNY/IIYG8k6+vVd3DiEc= xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”
把上面得到的代签名字符串使用MD5进行签名,并转为大写字母得到最后的签名串sign值。
String sign = MD5(signTempStr) = 782200BEFC4BB3C37E6F35C53BBFE34E