package cn.gistack.system.user.sync.util; import java.util.*; /** * 计算签名工具类; * 签名计算方法为: * * sign = MD5(自然排序(排除签名的所有参数) + [requestPath] + [requestMethod[POST|GET]] + secretKey); * 注意 requestMethod 已经经过大写转换处理; */ public class SignBuilder { public final static String TIMESTAMP_KEY = "timestamp"; public final static String CLIENT_ID_KEY = "clientId"; public final static String SIGN_KEY = "sign"; public final static String SALT_KEY = "salt"; private final String clientId; private final String clientSecret; private Long timestamp; private String salt; private String requestPath; private String requestMethod; private String sign; private final Map allParam = new TreeMap(); private SignBuilder(String clientId, String clientSecret) { this.clientId = clientId; this.clientSecret = clientSecret; } public static SignBuilder create(String clientId, String clientSecret) { return new SignBuilder(clientId, clientSecret); } /** * 构建实例的时候 自动生成时间戳,通过 SignBuilder.getTimestamp() 获取时间戳 * @param clientId OAuth2.0中客户端ID 也称为 appId * @param clientSecret OAuth2.0中客户端秘钥 也称为 appSecret */ public static SignBuilder createWithTimestampAndSalt(String clientId, String clientSecret) { SignBuilder result = new SignBuilder(clientId, clientSecret); return result.timestamp(System.currentTimeMillis()).salt(); } public SignBuilder param(String key, Object value) { if (sign != null) { throw new RuntimeException("sign has been generated, can't change the param"); } if (SIGN_KEY.equals(key)) { return this; } if (TIMESTAMP_KEY.equals(key)) { this.timestamp = Long.valueOf(String.valueOf(value)); } if (SALT_KEY.equals(key)) { this.salt = String.valueOf(value); } allParam.put(key, value); return this; } public SignBuilder params(Map params) { if (params == null) { return this; } for (Map.Entry entry : params.entrySet()) { param(entry.getKey(), entry.getValue()); } return this; } /** * 设置时间戳 * @param timestamp 时间戳 */ public SignBuilder timestamp(Long timestamp) { param(TIMESTAMP_KEY, timestamp); return this; } public SignBuilder requestPath(String requestPath) { if (sign != null) { throw new RuntimeException("sign has been generated, can't change the param"); } this.requestPath = requestPath; return this; } public SignBuilder requestMethod(String requestMethod) { if (sign != null) { throw new RuntimeException("sign has been generated, can't change the param"); } if (requestMethod != null) { this.requestMethod = requestMethod.toUpperCase(); } return this; } public SignBuilder salt() { return salt(Math.random()); } public SignBuilder salt(Object salt) { param(SALT_KEY, salt); return this; } /** * 获取 http 请求参数 */ public Map getQueryParamMap() { Map result = new HashMap(allParam); result.put(SIGN_KEY, sign()); return result; } /** * debug使用,获取签名前的原文;
* 秘钥已脱敏,使用 {clientSecret} 代替 */ public String getRawDataBeforeSign() { return rawDataBeforeSign() + "{clientSecret}"; } private String rawDataBeforeSign() { allParam.put(CLIENT_ID_KEY, clientId); if (timestamp != null && !allParam.containsKey(TIMESTAMP_KEY)) { allParam.put(TIMESTAMP_KEY, timestamp); } StringBuilder sb = new StringBuilder(); for (Object value : allParam.values()) { if (value != null) { sb.append(String.valueOf(value).trim()); } } if (requestPath != null) { sb.append(requestPath); } if (requestMethod != null) { sb.append(requestMethod.toUpperCase()); } return sb.toString(); } /** * 计算当前参数的签名,已经计算签名后,所有参数不可更改 */ public String sign() { if (sign != null) { return sign; } this.sign = MD5Util.getMD5String(rawDataBeforeSign() + clientSecret); if (this.sign == null) { return ""; } return this.sign.toUpperCase(); } public String getSalt() { return salt; } public String getClientId() { return clientId; } public Long getTimestamp() { return timestamp; } }