You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java环境下如何使用已有的访问密钥与密钥生成HMAC-SHA256签名访问REST API

Java Implementation for HMAC-SHA256 API Signature

Hey there, let's break down how to replicate that Python HTTP signature logic in Java. The core idea is generating an HMAC-SHA256 signature for a specific set of headers, then attaching it to your POST request's Authorization header. Here's a step-by-step solution with both standard library and Apache HttpClient examples.

Key Things to Replicate

First, let's align with what your Python code does:

  1. Sign a fixed list of headers: (request-target), host, date, content-type, content-length
  2. Use your base64-decoded secret key to generate the HMAC-SHA256 signature
  3. Format the signature into a valid Signature scheme Authorization header
  4. Send the POST request with all required headers and JSON body

Example 1: Using Standard Java Libraries (No External Dependencies)

This uses HttpURLConnection and Java's built-in crypto tools—no extra libraries needed:

import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class ApiSignatureHandler {
    public static void main(String[] args) throws Exception {
        // Replace with your actual values
        String host = "api.your-service.com";
        String urlPath = "/v1/your-endpoint";
        String keyId = "your-access-key-id";
        String base64EncodedSecret = "your-base64-secret-key"; // Same as key_secret_id in Python
        String jsonBody = "{\"data\": \"your-payload\"}";
        
        // 1. Prepare required header values
        String requestMethod = "POST";
        String requestTarget = requestMethod.toLowerCase() + " " + urlPath;
        String contentType = "application/json";
        long contentLength = jsonBody.getBytes(StandardCharsets.UTF_8).length;
        String dateHeader = DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now());
        
        // 2. Build the signing string (exact order matters!)
        StringBuilder signingString = new StringBuilder();
        signingString.append("(request-target): ").append(requestTarget).append("\n");
        signingString.append("host: ").append(host).append("\n");
        signingString.append("date: ").append(dateHeader).append("\n");
        signingString.append("content-type: ").append(contentType).append("\n");
        signingString.append("content-length: ").append(contentLength);
        
        // 3. Generate HMAC-SHA256 signature
        byte[] secretKeyBytes = Base64.getDecoder().decode(base64EncodedSecret);
        Mac hmacSha256 = Mac.getInstance("HmacSHA256");
        hmacSha256.init(new SecretKeySpec(secretKeyBytes, "HmacSHA256"));
        byte[] signatureBytes = hmacSha256.doFinal(signingString.toString().getBytes(StandardCharsets.UTF_8));
        String base64Signature = Base64.getEncoder().encodeToString(signatureBytes);
        
        // 4. Build the Authorization header
        String authHeader = String.format(
            "Signature keyId=\"%s\",algorithm=\"hmac-sha256\",headers=\"(request-target) host date content-type content-length\",signature=\"%s\"",
            keyId, base64Signature
        );
        
        // 5. Send the POST request
        URL apiUrl = new URL("https://" + host + urlPath);
        HttpURLConnection conn = (HttpURLConnection) apiUrl.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Host", host);
        conn.setRequestProperty("Date", dateHeader);
        conn.setRequestProperty("Content-Type", contentType);
        conn.setRequestProperty("Content-Length", String.valueOf(contentLength));
        conn.setRequestProperty("Authorization", authHeader);
        conn.setDoOutput(true);
        
        // Write the JSON body
        try (OutputStream os = conn.getOutputStream()) {
            byte[] payloadBytes = jsonBody.getBytes(StandardCharsets.UTF_8);
            os.write(payloadBytes, 0, payloadBytes.length);
        }
        
        // Handle the response
        int responseCode = conn.getResponseCode();
        System.out.println("Response Code: " + responseCode);
        // Add code to read response body if needed
    }
}

Example 2: Using Apache HttpClient 5.x

If you prefer using Apache HttpClient for cleaner request handling, here's how to do it:

First, add this Maven dependency (if using Maven):

<dependency>
    <groupId>org.apache.httpcomponents.client5</groupId>
    <artifactId>httpclient5</artifactId>
    <version>5.2.1</version>
</dependency>

Then the code:

import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.io.entity.StringEntity;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class ApacheHttpClientSignatureExample {
    public static void main(String[] args) throws Exception {
        // Replace with your actual values
        String host = "api.your-service.com";
        String urlPath = "/v1/your-endpoint";
        String keyId = "your-access-key-id";
        String base64EncodedSecret = "your-base64-secret-key";
        String jsonBody = "{\"data\": \"your-payload\"}";
        
        // Prepare header values
        String requestMethod = "POST";
        String requestTarget = requestMethod.toLowerCase() + " " + urlPath;
        String contentType = ContentType.APPLICATION_JSON.getMimeType();
        long contentLength = jsonBody.getBytes(StandardCharsets.UTF_8).length;
        String dateHeader = DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now());
        
        // Build signing string
        StringBuilder signingString = new StringBuilder();
        signingString.append("(request-target): ").append(requestTarget).append("\n");
        signingString.append("host: ").append(host).append("\n");
        signingString.append("date: ").append(dateHeader).append("\n");
        signingString.append("content-type: ").append(contentType).append("\n");
        signingString.append("content-length: ").append(contentLength);
        
        // Generate signature
        byte[] secretKeyBytes = Base64.getDecoder().decode(base64EncodedSecret);
        Mac hmacSha256 = Mac.getInstance("HmacSHA256");
        hmacSha256.init(new SecretKeySpec(secretKeyBytes, "HmacSHA256"));
        byte[] signatureBytes = hmacSha256.doFinal(signingString.toString().getBytes(StandardCharsets.UTF_8));
        String base64Signature = Base64.getEncoder().encodeToString(signatureBytes);
        
        // Build Authorization header
        String authHeader = String.format(
            "Signature keyId=\"%s\",algorithm=\"hmac-sha256\",headers=\"(request-target) host date content-type content-length\",signature=\"%s\"",
            keyId, base64Signature
        );
        
        // Create and send request
        HttpPost postRequest = new HttpPost("https://" + host + urlPath);
        postRequest.setEntity(new StringEntity(jsonBody, ContentType.APPLICATION_JSON));
        postRequest.setHeader("Host", host);
        postRequest.setHeader("Date", dateHeader);
        postRequest.setHeader("Content-Length", String.valueOf(contentLength));
        postRequest.setHeader("Authorization", authHeader);
        
        try (CloseableHttpClient client = HttpClients.createDefault();
             CloseableHttpResponse response = client.execute(postRequest)) {
            System.out.println("Response Code: " + response.getCode());
            // Process response body here
        }
    }
}

Critical Notes to Avoid Issues

  • Date Header Format: Make sure the Date header uses RFC 1123 format (e.g., Wed, 20 Sep 2023 14:30:00 GMT). The examples use Java 8+ ZonedDateTime to generate this correctly.
  • Header Order: The order of headers in the signing string must exactly match the list provided—any deviation will cause the signature to be invalid.
  • Secret Key Decoding: Your secret key is base64-encoded, so we decode it to bytes before generating the HMAC (just like the Python b64decode call).
  • Lowercase Header Names: The header names in the signing string are lowercase (e.g., content-type not Content-Type)—this is required for the API to validate the signature correctly.

内容的提问来源于stack exchange,提问作者Zakaria Shahed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 03:12:55