package com.zzwtec.wechat.rpc; import java.util.HashMap; import java.util.Map; import static com.xiaoleilu.hutool.util.ArrayUtil.isEmpty; import static com.xiaoleilu.hutool.util.StrUtil.isBlank; import static com.zzwtec.wechat.util.security.EncoderHandler.*; /** * 参数签名 */ public class Signature { private String appid; private String secretKey; private String headerSign; private String signAlgorithm; private static final String APPID = "appid"; private static final String SIGN = "sign"; public static final String ZZW_SIGN_HEADER = "zzw-sign"; public Signature(String appid, String secretKey, String headerSign, String signAlgorithm) { this.appid = appid; this.secretKey = secretKey; this.headerSign = headerSign; this.signAlgorithm = signAlgorithm; } public String getAppid() { return appid; } public Signature setAppid(String appid) { this.appid = appid; return this; } public String getSecretKey() { return secretKey; } public Signature setSecretKey(String secretKey) { this.secretKey = secretKey; return this; } public String getHeaderSign() { return headerSign; } public Signature setHeaderSign(String headerSign) { this.headerSign = headerSign; return this; } public String getSignAlgorithm() { return signAlgorithm; } public Signature setSignAlgorithm(String signAlgorithm) { this.signAlgorithm = signAlgorithm; return this; } @Override public String toString() { final StringBuffer sb = new StringBuffer("Signature{"); sb.append("appid='").append(appid).append('\''); sb.append(", secretKey='").append(secretKey).append('\''); sb.append(", headerSign='").append(headerSign).append('\''); sb.append(", signAlgorithm='").append(signAlgorithm).append('\''); sb.append('}'); return sb.toString(); } public boolean validateSign(String body) { notNull(headerSign, "headerSign is empty"); String calculateSign = sign(body); return calculateSign.equalsIgnoreCase(headerSign); } public String sign(String body) { notNull(secretKey, "secretKey is empty"); notNull(signAlgorithm, "signAlgorithm is empty"); String plain = body + secretKey; if (signAlgorithm.equals("MD5")) { return MD5(plain); } else if (signAlgorithm.equals("SHA1")) { return SHA1(plain); } else if (signAlgorithm.equals("SHA512")) { return SHA512(plain); } throw new IllegalStateException("never reach here"); } public static String toHeader(Signature signature, String body) { notNull(signature.appid, "appid is empty"); String sign = signature.sign(body); StringBuilder builder = new StringBuilder(APPID.length() + signature.getAppid().length() + SIGN.length() + sign.length() + 3); builder.append(APPID).append("=").append(signature.getAppid()).append(";").append(SIGN).append("=").append(sign); return builder.toString(); } public static Signature parseHeader(String signHeader) { if (isBlank(signHeader)) { return null; } String[] signs = signHeader.split(";"); if (isEmpty(signs)) { return null; } Map map = new HashMap<>(); for (String sign : signs) { String[] kv = sign.split("="); if (isEmpty(kv) || kv.length != 2) { continue; } if (kv[0].equals(APPID)) { map.put(kv[0], kv[1]); } else if (kv[0].equals(SIGN)) { map.put(kv[0], kv[1]); } } if (!map.containsKey(APPID) || !map.containsKey(SIGN)) { return null; } return new Signature(map.get(APPID), null, map.get(SIGN), null).setSignAlgorithm(); } public static void notNull(Object object, String message) { if (object == null) { throw new IllegalArgumentException(message); } } private Signature setSignAlgorithm() { if (headerSign.length() == 32) { this.signAlgorithm = "MD5"; } else if (headerSign.length() == 40) { this.signAlgorithm = "SHA1"; } else if (headerSign.length() == 128) { this.signAlgorithm = "SHA512"; } else { throw new IllegalArgumentException("unsupported algorithm"); } return this; } }