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

Postman正常的AWS Prometheus GET请求,Java HttpURLConnection返回403

调用Amazon Prometheus Server时Java HttpURLConnection返回403认证错误

我使用Postman请求Amazon Prometheus Server可正常返回结果,但通过Java的HttpURLConnection发起相同请求时,却返回403认证错误,认证采用AWS Signature Version 4签名机制。

Postman请求头(敏感信息已隐藏)

GET https://{resource}-workspaces.us-east-1.amazonaws.com/XXXXXXXXXXX/api/v1/query

Host: {resource}-workspaces.us-east-1.amazonaws.com
X-Amz-Security-Token: FwoGZXIvYXdzEB4aDPxYxIKgd5JznR9gOyKkAkoDbjeTi79mRDgU6Hdd2AGlLwKnNGySAkNYwmKItTcSssS9zNZ+/s..........................................==
X-Amz-Date: 20221207T201649Z
Authorization: AWS4-HMAC-SHA256 Credential={AccessKey}/20221207/us-east-1/{Resource}/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature=XXXXXXXXXXXXXXXXXXXXXXXXXX
User-Agent: PostmanRuntime/7.29.0
Accept: */*
Cache-Control: no-cache
Postman-Token: ea3f71dd-db52-4869-a48a-2cf5f72d15b3
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

Java HttpURLConnection代码

try { 
    final URL url = new URL("https://{resource}-workspaces.us-east-1.amazonaws.com/XXXXXXXXXXX/api/v1/query");

    final HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
    httpConn.setRequestMethod("GET");

    httpConn.setRequestProperty("Host", "{resource}-workspaces.us-east-1.amazonaws.com");
    httpConn.setRequestProperty("X-Amz-Security-Token", "FwoGZXIvYXdzEB4aDPxYxIKgd5JznR9gOyKkAkoDbjeTi79mRDgU6Hdd2AGlLwKnNGySAkNYwmKItTcSssS9zNZ+/s..........................................==");
    httpConn.setRequestProperty("X-Amz-Date", "20221207T201649Z");
    httpConn.setRequestProperty("Authorization", "AWS4-HMAC-SHA256 Credential={AccessKey}/20221207/us-east-1/{Resource}/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature=XXXXXXXXXXXXXXXXXXXXXXXXXX");
    httpConn.setRequestProperty("User-Agent", "Mozilla/5.0");
    httpConn.setRequestProperty("Accept", "`*`/`*`");
    httpConn.setRequestProperty("Cache-Control", "no-cache");
    httpConn.setRequestProperty("Postman-Token", "ea3f71dd-db52-4869-a48a-2cf5f72d15b3");
    httpConn.setRequestProperty("Accept-Encoding", "gzip, deflate, br");
    httpConn.setRequestProperty("Connection", "keep-alive");

    responseCode = httpConn.getResponseCode();  // 此处返回403
} 

已尝试的方案

  • 自行生成签名,而非复用Postman生成的签名
  • 添加/移除部分请求头,包括User-Agent、Accept、Cache-Control、Postman-Token、Accept-Encoding、Connection

请问是什么原因导致了403响应?我使用AWS Signature Version 4签名请求AWS服务,期望返回200,但实际得到403。


问题分析与解决建议

  1. 请求头格式错误
    你代码里的Accept头写了"*/*",多余的反引号会导致请求头内容和签名生成时的预期不一致,AWS验证签名时会直接拒绝,改成"*/*"即可。

  2. X-Amz-Date过期
    代码里复用了Postman的固定时间戳20221207T201649Z,AWS SigV4要求请求时间和签名时间差不能超过15分钟,过期的时间戳会直接触发403。即使自行生成签名,也要确保X-Amz-Date用当前请求的实时时间,且和签名生成时的时间完全一致。

  3. 签名与请求头的一致性问题
    AWS SigV4会校验SignedHeaders里指定的所有请求头,任何不一致都会导致验证失败:

    • 手动设置的Host头可能和HttpURLConnection自动生成的冲突,建议去掉手动设置,让框架自动从URL提取
    • Postman-Token是Postman的自定义头,不需要在Java请求中发送,如果签名时包含了这个头但实际没发,或者反之,都会导致签名不匹配
  4. HttpURLConnection自动行为干扰
    框架会自动处理Connection、Accept-Encoding这类头,手动设置可能和自动生成的内容冲突,比如编码格式的细节差异,建议只保留签名必需的头(X-Amz-Date、X-Amz-Security-Token、Authorization、User-Agent),其余交给框架处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 07:00:58