Micronaut 3.10.3对比3.10.2的哪些变更引发SSLHandshake失败?
升级Micronaut BOM至3.10.3后SSL握手失败问题分析
问题描述
仅将Micronaut BOM从3.10.2升级至3.10.3后,所有应用出现SSL连接错误,错误堆栈如下:
io.micronaut.http.client.exceptions.HttpClientException: <JKS_URL_HERE_works_fine_from_browser>: Connect Error: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at com.td.vsx.common.mn.ErrorTracingHttpClientFilter$DelegatingPublisher.replaceExceptionIncludingUrl(ErrorTracingHttpClientFilter.java:101) at com.td.vsx.common.mn.ErrorTracingHttpClientFilter$DelegatingPublisher$1.onError(ErrorTracingHttpClientFilter.java:80) at reactor.core.publisher.FluxMap$MapSubscriber.onError(FluxMap.java:134) at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:106) at reactor.core.publisher.Operators.error(Operators.java:198) at reactor.core.publisher.MonoError.subscribe(MonoError.java:53) at reactor.core.publisher.Mono.subscribe(Mono.java:4576) at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103) at reactor.core.publisher.FluxMap$MapSubscriber.onError(FluxMap.java:134) at reactor.core.publisher.MonoNext$NextSubscriber.onError(MonoNext.java:93) at reactor.core.publisher.MonoNext$NextSubscriber.onError(MonoNext.java:93) at io.micronaut.core.async.propagation.ReactivePropagation$2.onError(ReactivePropagation.java:129) at io.micronaut.http.reactive.execution.FlowAsMono$SubscriptionImpl.forward(FlowAsMono.java:132) at io.micronaut.http.reactive.execution.FlowAsMono$SubscriptionImpl.lambda$request$0(FlowAsMono.java:119) at io.micronaut.core.execution.ImperativeExecutionFlowImpl.onComplete(ImperativeExecutionFlowImpl.java:132) at io.micronaut.core.execution.DelayedExecutionFlowImpl$OnComplete.apply(DelayedExecutionFlowImpl.java:383) at io.micronaut.core.execution.DelayedExecutionFlowImpl.work(DelayedExecutionFlowImpl.java:54) at io.micronaut.core.execution.DelayedExecutionFlowImpl.complete0(DelayedExecutionFlowImpl.java:75) at io.micronaut.core.execution.DelayedExecutionFlowImpl.completeExceptionally(DelayedExecutionFlowImpl.java:87) at io.micronaut.http.client.netty.PoolResizer$PendingRequest.tryCompleteExceptionally(PoolResizer.java:429) at io.micronaut.http.client.netty.ConnectionManager$Pool.onNewConnectionFailure(ConnectionManager.java:1243) at io.micronaut.http.client.netty.ConnectionManager$Pool$1.onNewConnectionFailure(ConnectionManager.java:1205) at io.micronaut.http.client.netty.InitialConnectionErrorHandler.channelInactive(InitialConnectionErrorHandler.java:48) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:303) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:281) at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:274) at io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:81) at io.netty.handler.ssl.ApplicationProtocolNegotiationHandler.channelInactive(ApplicationProtocolNegotiationHandler.java:167) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:303) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:281) at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:274) at io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:412) at io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:377) at io.netty.handler.ssl.SslHandler.channelInactive(SslHandler.java:1192) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:303) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:281) at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:274) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1352) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:301) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:281) at io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:850) at io.netty.channel.AbstractChannel$AbstractUnsafe$7.run(AbstractChannel.java:811) at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:173) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:166) at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:566) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:998) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:842)
可能的原因分析
1. Netty版本升级带来的SSL验证逻辑变更
Micronaut 3.10.3大概率升级了底层依赖的Netty版本,新版本的Netty SSL Handler对证书链的验证逻辑更严格:
- 不再默认信任不完整的证书链(如服务器未正确返回中间证书)
- 对证书扩展字段(如Subject Alternative Name)的验证要求更高
- 修改了PKIX路径构建规则,导致JVM默认信任库无法匹配证书路径
2. Micronaut HTTP客户端SSL默认配置调整
3.10.3版本可能调整了HTTP客户端的默认SSL配置:
- 默认启用严格的证书验证模式,关闭了3.10.2中可能存在的宽松兼容选项
- 修改了信任库加载逻辑,不再自动加载系统信任库之外的自定义证书
- 调整
micronaut.http.client.ssl下的默认属性值,比如trust-all默认改为false
3. 证书路径构建逻辑优化
Micronaut在3.10.3中修改了PKIX证书路径构建的实现:
- 不再自动尝试补充缺失的中间证书
- 对证书有效性检查更全面,比如拒绝过期或吊销状态的证书(即使之前版本未严格校验)
排查与解决建议
- 验证证书链完整性:检查目标服务器返回的证书链是否包含所有必要的中间证书,可通过浏览器查看证书详情确认;若缺失,需将中间证书添加到应用的信任库或服务器配置中。
- 对比版本配置差异:查看Micronaut 3.10.3的发布说明,确认是否有
micronaut.http.client.ssl相关的默认配置变更,针对性调整应用配置。 - 临时宽松验证排查:添加配置
micronaut.http.client.ssl.insecure=true(仅用于测试),若连接恢复正常,说明是验证逻辑变严格导致的问题,需补充对应证书到信任库。 - 检查自定义SSL配置:若应用使用了自定义信任库或SSL上下文,确认3.10.3版本中加载逻辑是否正常,比如文件路径、权限是否符合要求。
内容的提问来源于stack exchange,提问作者Max Volkov
相关产品推荐
相关产品推荐

