开发者

SpringBoot3使用RestTemplate请求接口忽略SSL证书的问题解决

目录
  • 概述
  • 错误原因
  • 解决方案
    • 1. 将服务器证书添加到 Java 的信任库
    • 2. 忽略http://www.devze.com SSL 证书验证(不推荐)
    • 3. 使用受信任的证书
  • 总结

    概述

    我在项目中使用SpringBoot3版本+中RestTemplate请求接口时候报错:

    PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to fin

    注意:springBoot3版本+RestTemplate对应的是spring-web-6.+版本旧版本不适用以下解决方案,构建RestTemplateConfigl类可能会找不到对应方法!!!

    错误原因

    在使用 RestTemplate 调用 HTTPS 接口时,出现 PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderExhttp://www.devze.comception: unable to find valid certification path to requested target 错误,通常是因为 Java 应用程序无法验证服务器的 SSL 证书。

    具体原因如下:

    • 证书不受信任:Java 的默认信任库(cacerts)中没有包含服务器使用的 SSL 证书或中间证书。Java 使用这个信任库来验证服务器的证书链。
    • 自签名证书:如果服务器使用的是自签名证书,而不是由受信任的证书颁发机构(CA)签发的证书,Java 默认不会信任这种证书。
    • 证书链不完整:服务器的 SSL 证书链不完整,缺少中间证书,导致 Java 无法构建完整的证书路径。

    解决方案

    1. 将服务器证书添加到 Java 的信任库

    如果服务器使用的是自签名证书或不受信任的证书,可以将该证书添加到 Java 的信任库中。

    步骤:

    获取服务器证书

    • 使用浏览器访问目标 HTTPS 接口,导出服务器的 SSL 证书。
    • 或者使用 openssl 命令获取证书:
    openssl s_rNbIhqOvclient -connect <服务器地址>:443 -showcerts

      将输出中的证书部分保存为 .crt 文件。

      将证书导入 Java 信任库

      • 找到 Java 的 cacerts 文件,通常位于 $JAVA_HOME/lib/security/cacerts
      • 使用 keytool 将证书导入信任库:
      keytool -import -trustcacerts -file <证书文件> -keystore $JAVA_HOME/lib/security/cacerts -alias <别名>

      默认密码是 changeit

      重启应用程序:确保应用程序重新加载信任库。

      2. 忽略 SSL 证书验证(不推荐)

      如果你在开发环境中,且不关心证书验证,可以临时忽略 SSL 证书验证。注意:这种方法不安全,不推荐在生产环境中使用。

      步骤:

      自定义 RestTemplate:

      • 创建一个自定义的 SSLContext,忽略证书验证。
      • 使用 NoopHostnameVerifier 忽略主机名验证。
      import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
      import org.apache.hc.client5.http.impl.classic.HttpClients;
      import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
      import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
      import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder;
      import org.apache.hc.client5.http.ssl.TrustAllStrategy;
      import org.apache.hc.core5.ssl.SSLContextBuilder;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.http.client.ClientHttpRequestFactory;
      import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
      import org.springframework.web.client.RestTemplate;
      
      import java.security.KeyManagementException;
      import java.security.KeyStoreException;
      import java.security.NoSuchAlgorithmException;
      
      
      @Configuration
      public class RestTemplateConfig {
      
          @Bean
          public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
              return new RestTemplate(factory);
          }
      
          @Bean
          public ClientHttpRequestFactory simpleClientHttpRequestFactory() throws Exception {
              HttpComponentsClientHttpRequestFactory factory = generateHttpRequestFactory();
              factory.setConnectTimeout(15000);
              factory.setConnectionRequestTimeout(5000);
              return factory;
          }
      
          /**
           * 构造跳过SSL ClientHttp工厂
           *
           * @return
           * @throws NoSuchAlgorithmException
           * @throws KeyManagementException
           * @throws KeyStoreException
           */
          public static HttpComponentsClientHttpRequestFactory generateHttpRequestFactory()
                  throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
              CloseableHttpClient httpclient = HttpClients.custom()
                      .setConnectionManager(PoolingHttpClientConnectionManagerBuilder.create()
           rNbIhqOv                   .setSSLSocketFactory(SSLConnectionSocketFactoryBuilder.create()
                                      .setSslContext(SSLContextBuilder.create()
                                              .loadTrustMaterial(TrustAllStrategy.INSTANCE)
                                              .build())
                                      .setHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                                      .build())
                              .build())
                      .build();
              HttpComponentsClientHttpReqrNbIhqOvuestFactory factory = new HttpComponentsClientHttpRequestFactory();
              factory.setHttpClient(httpclient);
              return factory;
          }
      }

      使用自定义的 RestTemplate:

      在调用 HTTPS 接口时,使用上述方法创建的 RestTemplate

      3. 使用受信任的证书

      如果可能,建议使用由受信任的 CA 签发的证书,而不是自签名证书。这样可以避免证书验证问题。

      总结

      • 推荐方案:将服务器证书添加到 Java 的信任库中,确保证书链完整且受信任。
      • 临时方案:在开发环境中,可以临时忽略 SSL 证书验证,但不建议在生产环境中使用。
      • 最佳实践:使用受信任的 CA 签发的证书,确保 SSL/TLS 通信的安全性。

      到此这篇关于SpringBoot3使用RestTemplate请求接口忽略SSL证书的问题解决的文章就介绍到这了,更多相关SpringBoot3 RestTemplate忽略SSL证书内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新开发

      开发排行榜