package org.springblade.modules.signature.util; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springblade.common.utils.HttpClientUtils; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.GeneralSecurityException; import java.security.MessageDigest; import java.util.*; /** * sign 生成工具类 * @author zhongrj * @since 2022-03-11 */ public class SignUtil { private static Logger LOGGER = LoggerFactory.getLogger(SignUtil.class); /** * 获取签名sign * @param params 参数集合不含appSecret * @param secret 验证接口的appSecret * @return */ public static String getSign(Map params,String secret) { String sign=""; StringBuilder sb = new StringBuilder(); //1. 先对请求参数排序 Set keyset=params.keySet(); TreeSet sortSet=new TreeSet<>(); sortSet.addAll(keyset); Iterator it=sortSet.iterator(); //2. 把参数的key value链接起来 ,再把appSecret拼接参数字符串的最后面,得到要加密的字符串 while(it.hasNext()) { String key=it.next(); String value=params.get(key).toString(); sb.append(key).append(value); } sb.append(secret); byte[] md5Digest; try { //3. Md5加密 md5Digest = getMD5Digest(sb.toString()); //4.得到sign sign = byte2hex(md5Digest); } catch (IOException e) { LOGGER.error("生成签名错误",e); } // 5. 返回 sign return sign; } /** * 回调接口验证签名方法 * @param request * @return */ public static Boolean checkSign(HttpServletRequest request,String appSecret){ Boolean flag= false; String sign = request.getParameter("sign");//签名 if(StringUtils.isEmpty(sign)){ return false; } //检查sign是否过期 Enumeration pNames = request.getParameterNames(); Map params = new HashMap<>(); while (pNames.hasMoreElements()) { String pName = (String) pNames.nextElement(); if("sign".equals(pName)) { continue; } String pValue = request.getParameter(pName); params.put(pName, pValue); } if(sign.equals(getSign(params, appSecret))){ flag = true; } return flag; } /** * MD5加密数据方法 */ private static byte[] getMD5Digest(String data) throws IOException { byte[] bytes = null; try { MessageDigest md = MessageDigest.getInstance("MD5"); bytes = md.digest(data.getBytes("UTF-8")); } catch (GeneralSecurityException gse) { throw new IOException(gse); } return bytes; } /** * MD5加密数据后的数据处理方法 */ private 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(); } public static String utf8Encoding(String value, String sourceCharsetName) { try { return new String(value.getBytes(sourceCharsetName), "UTF-8"); } catch (UnsupportedEncodingException e) { throw new IllegalArgumentException(e); } } /** 测试方法 */ public static void main(String[] args) { //参数签名算法测试例子 HashMap signMap = new HashMap(); String appkey = "584561146"; signMap.put("appKey",appkey); // System.out.println("得到签名sign1:"+getSign(signMap,"454sd5fa45dsa5fdaf54")); String sign = getSign(signMap, "454sd5fa45dsa5fdaf54"); signMap.put("sign",sign); HttpClientUtils.postParams("http://localhost:81/attendance/AppSave", appkey, signMap); } }