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`,建议做一次全仓库扫描与统一治理。


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

相关推荐
yyuuuzz9 小时前
独立站的技术基础与常见运维问题
大数据·运维·服务器·网络·数据库·aws
代码N年归来仍是新手村成员2 天前
【AWS】Lambda 初识与服务部署
javascript·react.js·ai·node.js·云计算·ai编程·aws
zhojiew3 天前
在AWS裸金属实例上安装Cubesandbox并集成PydanticAI进行数据分析的实践
数据分析·云计算·aws
yyuuuzz3 天前
aws亚马逊云上运维常见问题梳理
运维·服务器·网络·云计算·aws
亚林瓜子4 天前
AWS S3日志桶常用过期文件生命周期策略
云计算·生命周期·aws·s3·过期·glacier
yyuuuzz4 天前
企业出海场景下的技术适配小经验
运维·服务器·网络·云计算·aws
yyuuuzz6 天前
国外云服务使用的常见技术问题梳理
运维·服务器·网络·数据库·aws
光于前裕于后7 天前
AWS Redshift 集成Zero-ETL和数据共享 Data sharing
云计算·etl·aws
zhojiew9 天前
在AWS中国区实现EKS跨VPC跨区域实现节点加入集群的实践
云计算·aws
认真的薛薛9 天前
Terraform: AWS VPC+可SSH登录EC2
ssh·aws·terraform