使用Spring RestClient调用AWS S3预签名链接时的400错误排查
解决Spring RestClient调用S3预签名链接的签名错误问题
核心问题根源
Spring RestClient默认会对传入的URI参数进行自动编码,但S3预签名链接的所有查询参数(包括X-Amz-Credential、X-Amz-Security-Token)都是已经通过AWS签名算法生成的固定值,二次编码会破坏签名的有效性,导致AWS返回参数格式或无效Token的错误。
直接可行的解决方法
1. 直接传入URI对象而非字符串
跳过RestClient的自动解析编码逻辑,直接用Java原生URI类包装完整的预签名链接,保证参数完全原始:
RestClient restClient = RestClient.create(); // 直接把预签名链接转成URI对象 URI s3PreSignedUri = new URI("https://your-bucket.s3.amazonaws.com/object?X-Amz-Algorithm=...&X-Amz-Credential=...&X-Amz-Security-Token=..."); String responseBody = restClient.get() .uri(s3PreSignedUri) .retrieve() .body(String.class);
2. 强制关闭UriComponentsBuilder的自动编码(如果必须用Builder)
如果需要动态拼接部分参数,必须显式关闭自动编码,避免参数被篡改:
String preSignedUrl = "你的完整预签名链接"; UriComponents uriComponents = UriComponentsBuilder.fromUriString(preSignedUrl) .encode(false) // 关键:禁用自动编码 .build(); RestClient restClient = RestClient.create(); restClient.get() .uri(uriComponents.toUri()) .retrieve() .body(String.class);
排查验证步骤
- 对比请求报文:开启RestClient的DEBUG日志,打印完整请求URL,和curl/Bruno的请求URL逐字符对比,重点检查
X-Amz-Credential和X-Amz-Security-Token是否被转义(比如/变成%2F、+变成%2B)。
日志配置:logging.level.org.springframework.web.client.RestClient=DEBUG - 检查预签名链接完整性:确认预签名链接生成后没有被其他代码(比如
URLEncoder)二次处理,确保拿到的是AWS返回的原始签名链接。
内容的提问来源于stack exchange,提问作者Chanandler Bong
相关产品推荐
相关产品推荐

