指南在 Java 中请求签名

本文介绍了在 Java 中 请求签名 的示例实现。

# 依赖项

此示例使用 Java SDK 中的 utilnetcrypto 依赖项。

# 示例

以下简单示例实现了 请求签名 指南中描述的算法。最重要的是使用任何库按正确的顺序计算 HMAC-SHA-256methodurltimestampbody

method 参数应为大写,path 应仅包含 URL 中的相对路径和查询参数,而不是完整的 URL 地址。完整的 URL 地址应转换为例如 /webhook?a=1

如果算法正常工作,它应该生成与以下签名相同的签名:56ac656c7f932c5b775be28949e90af9a2356eae2826539f10ab6526a0eec762,对于以下参数

  • apiSecret=SECRET

  • method=POST

  • uri=http://demo.example.com/webhook?a=1

  • timestamp=1563276169752

  • body={a:1}

import java.util.Formatter;
import java.util.Map;
import java.net.URI;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.Mac;


public class Main {

    private static final String HMAC_SHA256 = "HmacSHA256";

    public static void main(String args[]) throws Exception {
        String expectedSignature = "56ac656c7f932c5b775be28949e90af9a2356eae2826539f10ab6526a0eec762";
        String signature = generateSignature(
            "SECRET",
            "POST",
            "http://demo.example.com/webhook?a=1",
            1563276169752l,
            "{\"a\":1}"
        );

        System.out.println(signature.equals(expectedSignature));
    }

    private static String toHexString(byte[] bytes) {
        Formatter formatter = new Formatter();

        for (byte b: bytes) {
            formatter.format("%02x", b);
        }

        return formatter.toString();
    }

    public static String calculateHMACSHA256(String data, String key) throws Exception {
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), HMAC_SHA256);
        Mac mac = Mac.getInstance(HMAC_SHA256);

        mac.init(secretKeySpec);

        return toHexString(mac.doFinal(data.getBytes()));
    }

    private static String generateSignature(String secret, String method, String uri, long timestamp) throws Exception {
        return generateSignature(secret, method, uri, timestamp, "");
    }

    private static String generateSignature(String secret, String method, String uri, long timestamp, String bodyString) throws Exception {
        String methodUpperCase = method.toUpperCase();
        URI url = new URI(uri);
        String path = url.getPath();
        String query = url.getQuery();

        if (!query.isBlank()) {
            path = path + "?" + query;
        }

        String signatureData = methodUpperCase + path + timestamp;

        if (bodyString != null) {
            signatureData += bodyString;
        }

        return calculateHMACSHA256(signatureData, secret);
    }
}