如何使用IAM权限向AWS API Gateway发起API请求(Java实现)
解决Java 11 HttpClient调用IAM授权的AWS API Gateway问题
你碰到的403错误是因为IAM授权的AWS API需要使用**AWS Signature Version 4(SigV4)**签名请求,不能直接在请求头里传递Access Key和Secret Key,必须对请求进行签名处理。以下是两种可行的解决方案:
方案一:通过环境变量加载凭证(推荐)
步骤1:引入AWS签名依赖
如果使用Maven,在pom.xml中添加轻量的AWS SDK依赖(避免引入全量SDK):
<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>auth</artifactId> <version>2.25.0</version> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>regions</artifactId> <version>2.25.0</version> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>signer</artifactId> <version>2.25.0</version> </dependency>
步骤2:修改代码实现签名
代码会自动从环境变量AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY加载凭证,完成SigV4签名后发送请求:
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Instant; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.signer.Signer; import software.amazon.awssdk.signer.SignerRequestParams; import software.amazon.awssdk.signer.SigningAlgorithm; import software.amazon.awssdk.signer.auth.SignerCredentials; class Main { public static void main(String[] args) throws Exception { // 从环境变量加载AWS凭证 EnvironmentVariableCredentialsProvider credentialsProvider = EnvironmentVariableCredentialsProvider.create(); AwsBasicCredentials credentials = (AwsBasicCredentials) credentialsProvider.resolveCredentials(); SignerCredentials signerCredentials = SignerCredentials.create(credentials.accessKeyId(), credentials.secretAccessKey()); // 配置签名参数:指定API所在区域、服务名称(API Gateway对应execute-api) Region region = Region.of("us-east-1"); String serviceName = "execute-api"; Instant signingInstant = Instant.now(); // 构建原始请求框架 URI apiUri = URI.create("https://abc123.execute-api.us-east-1.amazonaws.com/prod/controlplane/model/a1"); HttpRequest.Builder requestBuilder = HttpRequest.newBuilder() .uri(apiUri) .header("accept", "application/json") .header("x-amz-date", signingInstant.toString()); // 生成SigV4签名 SignerRequestParams params = SignerRequestParams.builder() .signingAlgorithm(SigningAlgorithm.AWS4_HMAC_SHA256) .credentials(signerCredentials) .signingName(serviceName) .signingRegion(region.id()) .signingDate(signingInstant) .requestUri(apiUri.getPath()) .httpMethod(requestBuilder.build().method()) .build(); Signer signer = Signer.create(); String authorizationHeader = signer.sign(params).authorizationHeader(); // 将签名添加到请求头并发送 HttpRequest request = requestBuilder .header("Authorization", authorizationHeader) .build(); HttpClient client = HttpClient.newHttpClient(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); // 输出响应结果 System.out.println(response); System.out.println(response.body()); } }
步骤3:设置环境变量
运行代码前,配置系统环境变量:
AWS_ACCESS_KEY_ID:你的AWS访问密钥IDAWS_SECRET_ACCESS_KEY:你的AWS秘密访问密钥
方案二:硬编码凭证(仅用于测试,不推荐)
如果暂时无法使用环境变量,可直接硬编码凭证(注意不要将代码提交到版本控制系统):
// 替换为你的实际凭证 AwsBasicCredentials credentials = AwsBasicCredentials.create("YOUR_ACCESS_KEY", "YOUR_SECRET_KEY"); SignerCredentials signerCredentials = SignerCredentials.create(credentials.accessKeyId(), credentials.secretAccessKey());
其余代码逻辑与方案一完全一致。
关键说明
- IAM授权的AWS API Gateway必须使用SigV4签名,直接传递密钥不会被服务端识别,这也是你收到
Missing Authentication Token错误的核心原因。 - 若在EC2、EKS等AWS托管服务中运行代码,还可以直接绑定IAM角色,无需手动配置密钥,SDK会自动从实例元数据加载凭证。
内容的提问来源于stack exchange,提问作者dredbound
相关产品推荐
相关产品推荐

