feat:外部接口接入

This commit is contained in:
苏竹红
2025-04-02 09:16:43 +08:00
parent a54644b8bd
commit d4cb86b415
7 changed files with 333 additions and 5 deletions

View File

@@ -6,7 +6,11 @@ import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
/**
@@ -17,6 +21,11 @@ import java.util.*;
@Slf4j
public class SignatureUtils {
private static final String HMAC_ALGORITHM = "HmacSHA256";
private static final DateTimeFormatter RFC_1123_FORMATTER =
DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH)
.withZone(ZoneId.of("GMT"));
/**
* 生成 HmacSHA256 签名
* @param data 待签名字符串
@@ -25,8 +34,8 @@ public class SignatureUtils {
*/
public static String hmacSha256(String data, String secret) {
try {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
Mac mac = Mac.getInstance(HMAC_ALGORITHM);
SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), HMAC_ALGORITHM);
mac.init(secretKey);
byte[] hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hash).toLowerCase();
@@ -35,6 +44,57 @@ public class SignatureUtils {
}
}
/**
* 生成与Postman一致的签名头
* @param username API用户名
* @param secret API密钥
* @param requestBody 请求体JSON字符串
* @return 包含所有签名头的Map
*/
public static Map<String, String> generateHeaders(String username,
String secret,
String requestBody) {
// 1. 生成RFC 1123格式时间戳
String date = ZonedDateTime.now(ZoneId.of("GMT")).format(RFC_1123_FORMATTER);
// 2. 计算请求体摘要
String digest = "SHA-256=" + calculateDigest(requestBody);
// 3. 构建签名字符串
String signingString = "x-date: " + date + "\n" + "digest: " + digest;
// 4. 计算HMAC签名
String signature = hmacSha256( signingString,secret);
// 5. 组装Authorization头
String authorization = String.format(
"hmac username=\"%s\", algorithm=\"hmac-sha256\", headers=\"x-date digest\", signature=\"%s\"",
username,
signature
);
// 6. 返回所有头信息
Map<String, String> headers = new HashMap<>();
headers.put("x-date", date);
headers.put("Digest", digest);
headers.put("Authorization", authorization);
return headers;
}
private static String calculateDigest(String data) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest(data.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(hash);
} catch (Exception e) {
throw new RuntimeException("Digest计算失败", e);
}
}
/**
* 生成待签名字符串(参数按字母排序 + appkey + timestamp
* @param params 请求参数Map需提前过滤空值
@@ -70,4 +130,7 @@ public class SignatureUtils {
}
return sb.toString();
}
}