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


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

相关推荐
A小辣椒4 天前
AWS Clould Support Engineer就职面试题
aws
亚林瓜子6 天前
AWS WAF中如何放行某个触发了托管规则的接口
aws·waf
悠悠121388 天前
AWS DevOps Agent 体验一周后,我决定把 oncall 手机调成静音了
云计算·aws·devops
yyuuuzz8 天前
独立站运营的几个技术层面常见问题
大数据·运维·服务器·网络·数据库·aws
yyuuuzz8 天前
游戏云服务器推荐的技术选择思路
大数据·运维·服务器·游戏·云计算·aws
kernelcraft10 天前
Boto3:Python 操作 AWS 的官方 SDK
开发语言·python·其他·aws
普通网友17 天前
Serverless 框架:多云函数部署(AWS + 阿里云 + 腾讯云)
阿里云·serverless·aws
TG_yunshuguoji17 天前
亚马逊云代理商:如何用 CloudWatch+Lambda 打造自动化告警系统
大数据·运维·自动化·云计算·aws
yyuuuzz17 天前
独立站搭建的几个核心技术问题
运维·服务器·网络·数据库·aws
yyuuuzz17 天前
aws亚马逊云服务的基础认知与常见场景
大数据·运维·服务器·网络·云计算·aws