You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java应用调用Microsoft Graph API时Azure登录出现间歇性证书验证失败问题

Java应用调用Microsoft Graph API时Azure登录出现间歇性证书验证失败问题

我最近碰到个特别棘手的问题:我开发的Java应用需要通过Microsoft Graph API访问邮箱,但这个操作时好时坏,失败的时候会抛出无效证书相关的错误,具体的异常日志如下:

2025-02-12 15:50:03.967 [mailbox-listener,,,] WARN HP5CD4411BBZ [reactor-http-nio-2] reactor.util.Loggers$Slf4JLogger - [ca541c56, L:/192.168.255.140:52273 ! R:login.microsoftonline.com/20.190.181.5:443] The connection observed an error
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: General OpenSslEngine problem
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:500)
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1357)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:868)
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
        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:1583)
Caused by: javax.net.ssl.SSLHandshakeException: General OpenSslEngine problem
        at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.handshakeException(ReferenceCountedOpenSslEngine.java:1928)
        at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.wrap(ReferenceCountedOpenSslEngine.java:853)
        at java.base/javax.net.ssl.SSLEngine.wrap(SSLEngine.java:564)
        at io.netty.handler.ssl.SslHandler.wrap(SslHandler.java:1137)
        at io.netty.handler.ssl.SslHandler.wrapNonAppData(SslHandler.java:981)
        at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1539)
        at io.netty.handler.ssl.SslHandler.decodeNonJdkCompatible(SslHandler.java:1377)
        at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1417)
        at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:530)
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:469)
        ... 17 common frames omitted
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:388)
        at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:271)
        at java.base/sun.security.validator.Validator.validate(Validator.java:256)
        at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:284)
        at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:144)
        at io.netty.handler.ssl.EnhancingX509ExtendedTrustManager.checkServerTrusted(EnhancingX509ExtendedTrustManager.java:69)
        at io.netty.handler.ssl.ReferenceCountedOpenSslClientContext$ExtendedTrustManagerVerifyCallback.verify(ReferenceCountedOpenSslClientContext.java:239)
        at io.netty.handler.ssl.ReferenceCountedOpenSslContext$AbstractCertificateVerifier.verify(ReferenceCountedOpenSslContext.java:836)
        at io.netty.internal.tcnative.CertificateVerifierTask.runTask(CertificateVerifierTask.java:36)
        at io.netty.internal.tcnative.SSLTask.run(SSLTask.java:48)
        at io.netty.internal.tcnative.SSLTask.run(SSLTask.java:42)
        at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.runAndResetNeedTask(ReferenceCountedOpenSslEngine.java:1534)
        at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.access$700(ReferenceCountedOpenSslEngine.java:94)
        at io.netty.handler.ssl.ReferenceCountedOpenSslEngine$TaskDecorator.run(ReferenceCountedOpenSslEngine.java:1506)
        at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1679)
        at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1525)
        ... 21 common frames omitted
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:148)
        at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:129)
        at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
        at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:383)
        ... 36 common frames omitted

我的项目使用的Maven依赖配置如下:

<properties>
    <microsoft-graph.version>6.27.0</microsoft-graph.version>
    <azure-identity.version>1.15.0</azure-identity.version>
</properties>
<!-- Microsoft Graph API gives access to, among other things, Exchange Cloud mailboxes -->
<dependencies>
    <dependency>
        <groupId>com.microsoft.graph</groupId>
        <artifactId>microsoft-graph</artifactId>
        <version>${microsoft-graph.version}</version>
    </dependency>
    <dependency>
        <!-- This dependency is only needed if you are using a TokenCredential object for authentication -->
        <groupId>com.azure</groupId>
        <artifactId>azure-identity</artifactId>
        <version>${azure-identity.version}</version>
    </dependency>
</dependencies>

对应的Spring Boot配置类代码(原代码存在截断,已补全关键部分以保证可读性):

@Configuration
@ConditionalOnProperty(prefix = "mailbox-processor", name = "microsoft-graph.authentication.client-id")
@Slf4j
public class MicrosoftGraphConfiguration {

    private static final String[] SCOPES = {"https://graph.microsoft.com/.default"};

    private final MicrosoftGraphProperties properties;

    public MicrosoftGraphConfiguration(final ApplicationProperties applicationProperties) {
        this.properties = applicationProperties.microsoftGraph();
    }

    @PostConstruct void postConstruct() {
        log.info("Microsoft graph configuration initialised");
    }

    private InetSocketAddress getProxyAddress() {
        final var proxy = properties.proxy();
        return new InetSocketAddress(proxy.host(), proxy.port());
    }

    @Bean TokenCredential azureClientCredential() {
        final var baseClient = HttpClient
                .create()
                .httpMessageLogFactory(new AbstractHttpMessageLogFactory() {
                    @Override public String common(final HttpMessageArgProvider provider) {
                        return HttpMessageLogUtils.logHttpMessage(
                                provider,
                                Function.identity(),
                                decoderResult -> {
                                    if (!decoderResult.isFinished()) {
                                        return "unfinished";
                                    } else if (decoderResult.isSuccess()) {
                                        return "success";
                                    } else {
                                        return "failure(" + decoderResult.cause() + ")";
                                    }
                                },
                                entry -> {
                                    if (HttpHeaders.AUTHORIZATION.equalsIgnoreCase(entry.getKey())) {
                                        return "<filtered>";
                                    } else {
                                        return entry.getValue();
                                    }
                                }
                        );
                    }
                })
                .wiretap("login.microsoftonline.com", LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL);
        final var httpClientBuilder = new NettyAsyncHttpClientBuilder(baseClient);
        final var proxyProperties = properties.proxy();
        if (proxyProperties != null) {
            final var proxyAddress = getProxyAddress();
            log.info("Using HTTP proxy {} (for authentication)", proxyAddress);
            final var proxyOptions = new ProxyOptions(ProxyOptions.Type.HTTP, getProxyAddress());

            final var user = proxyProperties.user();
            final var password = proxyProperties.password();
            if (StringUtils.isNoneBlank(user, password)) {
                proxyOptions.setCredentials(user, password);
            }
            httpClientBuilder.proxy(proxyOptions);
        }
        final var httpClient = httpClientBuilder.build();
        return new ClientSecretCredentialBuilder()
                .clientId(properties.authentication().clientId())
                .clientSecret(properties.authentication().clientSecret())
                .tenantId(properties.authentication().tenantId())
                .httpClient(httpClient)
                .build();
    }
}

备注:内容来源于stack exchange,提问作者SeverityOne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 09:59:33