AWS-S2上传提示证书错误

运营模块访问 S3 报 TLS 证书主机名不匹配:一次依赖版本导致的「假证书问题」

摘要

某 Spring 应用在通过 **AWS SDK for Java v2** 上传对象到 **Amazon S3** 时,抛出 **TLS 主机名与证书不匹配**。环境(JDK、网络、凭证)与另一套可正常运行的部署一致,差异仅在 **Maven 依赖**。最终定位到 **`org.apache.httpcomponents:httpclient` 被显式锁定为旧版**,覆盖了 AWS `apache-client` 所需的版本;将 **HttpClient 升级到与 SDK 一致(如 4.5.12)** 后问题消失。


背景

  • 应用使用 **`software.amazon.awssdk:s3`**(以及默认的 **`apache-client`**)访问对象存储。

  • 部分业务代码封装在公共模块(下文称 **「公共模块」**)中;运营类 Web 应用(下文称 **「运营模块」**)单独引入依赖树。

  • 现象:**同一套运行环境**下,A 部署正常,B 部署报错,对比发现 **B 未按与 A 相同方式引入公共模块或依赖版本不一致**。


现象与错误信息

上传或访问 S3 时出现类似异常(大意如下,具体主机名以实际为准):

  • **SSL / 证书校验失败**,提示 **peer 证书中的 CN/SAN** 与 **当前请求使用的主机名** 不一致。

  • 典型表述中会同时出现:

  • 访问域名形态类似:`*.s3.<region>.amazonaws.com`(点分区域名);

  • 证书侧可能是另一套历史通配符形态(如连字符区域名),从而加重「像是证书配错了」的错觉。

> **说明**:S3 在不同 endpoint 风格下主机名可能不同;若仅看到「主机名与证书不一致」,容易误判为 **证书配置错误或 DNS 劫持**,而忽略 **本地 HTTP/TLS 栈版本过旧** 的可能。


排查思路(简要)

  1. **确认 SDK 代际**:业务使用的是 **AWS SDK v2**(`software.amazon.awssdk`),不要与 v1(`com.amazonaws`)的依赖混谈。

  2. **对比可运行与不可运行产物的依赖**:重点看 **`software.amazon.awssdk`** 各模块版本是否一致,以及 **`apache-client`** 传递的 **`httpclient`** 是否被覆盖。

  3. **在 IDE 依赖分析或 `mvn dependency:tree` 中搜索** `org.apache.httpcomponents:httpclient`,确认 **最终解析版本**。


根因

在 **运营模块** 的 `pom.xml` 中,曾对 **`httpclient` 显式指定了较低版本**(例如 **4.4.x**)。

而 **`software.amazon.awssdk:apache-client`**(与 S3 等客户端配套)期望使用 **较新的 `httpclient`(例如 4.5.12)**。

Maven 解析时,**显式依赖往往优先**,导致:

  • 传递依赖中的 **`httpclient:4.5.12` 被标记为「与 4.4.x 冲突而省略」**;

  • 运行时实际加载 **旧版 HttpClient**,与 AWS 官方测试矩阵不一致;

  • 在 **TLS、SNI、主机名校验** 等路径上可能出现与新版不同的行为,从而表现为 **证书/主机名相关异常**(与「endpoint 主机名形态」等问题叠加时,日志更容易误导排查方向)。

**结论**:表面是「证书与主机名不匹配」,实质之一是 **HTTP 客户端版本被业务 POM 钉死,未与 AWS SDK 的 `apache-client` 对齐**。


解决方案

推荐做法(择一或组合)

  1. **将 `httpclient` 升级到与 `apache-client` 传递依赖一致**

例如在问题模块中显式使用 **4.5.12**(或与当前 `software.amazon.awssdk` BOM 中 `apache-client` 要求一致的版本)。

  1. **去掉无必要的显式 `httpclient` 依赖**

若没有特殊理由必须锁定版本,可删除该显式依赖,交由 **AWS SDK BOM + `apache-client`** 管理传递版本。

  1. **在父 POM 的 `dependencyManagement` 中统一**

避免各子模块各自钉 `httpclient` 版本,防止再次出现「某模块把全应用拉回旧版」的情况。

与「引入公共模块」为何能缓解

若公共模块的 POM 已使用 **较新的 `httpclient`**,且运营模块 **改为依赖公共模块并移除冲突的显式旧版本**,依赖树会与可运行环境对齐,问题随之消失。

**根本仍是版本对齐**,而不是「魔法依赖」。


验证建议

  • 构建后执行:

`mvn dependency:tree -Dincludes=org.apache.httpcomponents:httpclient`

确认最终解析为 **目标版本(如 4.5.12)**,且无与 AWS `apache-client` 冲突的省略提示。

  • 在测试环境做一次 **S3 上传/下载冒烟**,确认无 TLS 异常。

经验总结

| 要点 | 说明 |

|------|------|

| **显式依赖会覆盖传递依赖** | 特别是 `httpclient` 这类基础库,钉版本前确认与云 SDK、Spring 等栈兼容。 |

| **证书类报错先看依赖树** | 与环境无关、仅构建差异时,优先比对 **HTTP/TLS 相关组件版本**。 |

| **SDK v1 / v2 与 HTTP 实现不要混为一谈** | v2 使用 `software.amazon.awssdk` + `apache-client` / `netty` 等,排查时对齐 BOM。 |

| **长期维护** | 用 **BOM** 或 **父 POM 统一管理** 云 SDK 与 Apache HttpClient,减少漂移。 |


结语

本次问题说明:**基础设施类依赖的版本漂移,会以「TLS/证书」这种高敏感方式暴露出来**。把 **`httpclient` 与 AWS SDK v2 的 `apache-client` 对齐** 后,问题得到解决;若团队内仍有多个模块手写旧版 `httpclient`,建议做一次全仓库扫描与统一治理。


*本文中的业务名、模块名、存储桶名、区域与版本号均为说明用途;请按自身环境替换为实际值,勿在公开渠道泄露账号、密钥与真实桶名。*

相关推荐
亚马逊云开发者15 小时前
SDLC 过时了?从 2x 到 20x 效能的 AIDLC 转型实践 | Kiro + OpenClaw 实战
aws
亚马逊云开发者1 天前
从本地到云端 | OpenClaw Agent + Bedrock AgentCore SDK 部署全攻略
aws
Blue summer1 天前
使用AWS SSO + Terraform 管理AWS资源
云计算·aws·terraform
亚马逊云开发者2 天前
不用 Docker 也能跑 AI Agent | OpenClaw + Podman + EC2 Graviton + ECR 容器化部署全攻略
aws
海水冷却4 天前
RTC成语音AI基础设施:AWS和ElevenLabs相继跟进,ZEGO已跑三年
人工智能·实时音视频·aws
亚马逊云开发者5 天前
开了 GuardDuty 一周,发现 EC2 被人暴力破解 SSH 了
aws
亚马逊云开发者5 天前
Bedrock 调用次数比预期多了一倍?CloudTrail 5 分钟定位元凶
aws
亚马逊云开发者5 天前
API Key 还明文写在配置文件里?OpenClaw SecretRef 帮你摘出来
aws
zhojiew6 天前
[INFRA] EMR集群节点下线 (Decommission) 机制和逻辑深入分析
aws·emr·bigdata