spring cloud项目 用restTemplate 访问第三方https接口报错:ValidatorException: PKIX path building failed:

本文探讨了SpringCloud项目中遇到的HTTPS证书问题,通过配置信任所有证书和代码方式定制SSLContext解决,重点展示了如何在RestTemplate中设置自定义TrustManager。

场景:

今天有一个功能,spring cloud项目需要调用远程https 接口,使用 RestTemplate,本地测试无异常;部署到测试环境后报证书问题:异常如下:

I/O error on POST request for "https://gateway.xxx.com/yao/user/login": sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

解决办法1:因为是https证书问题,所以配置了信任所有证书,响应正常。

解决办法2:代码方式证书配置

代码如下:
    @Bean(name="restTemplateRemote")
    public RestTemplate restTemplateRemote() throws Exception {
        TrustManager[] trustAllCerts =new TrustManager[] {
                new X509TrustManager() {
                    @Override
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return new java.security.cert.X509Certificate[0];
                    }
                    @Override
                    public void checkClientTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                    }
                    @Override
                    public void checkServerTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                    }
                }
        };
        SSLContext sslContext =SSLContext.getInstance("SSL");
        sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
        CloseableHttpClient httpClient =HttpClients.custom()
                .setSSLContext(sslContext)
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                .build();
        HttpComponentsClientHttpRequestFactory customRequestFactory =new HttpComponentsClientHttpRequestFactory();
        customRequestFactory.setHttpClient(httpClient);
        return new RestTemplate(customRequestFactory);
    }
 

service层代码:

  此处因为是调用第三方https接口,并不是nacos注册中心的服务,所以不用@LoadBalanced注解

@Autowired
    @Qualifier(value = "restTemplateRemote")
    private RestTemplate restTemplate;

接口入参出参均为json格式数据

private String refreshToken(LoginVo vo){
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.setContentType(MediaType.parseMediaType("application/json; charset=UTF-8"));
            httpHeaders.add("Accept", MediaType.APPLICATION_JSON.toString());
            HttpEntity<String> formEntity = new HttpEntity<String>(JSONObject.toJSONString(vo), httpHeaders);
            String post = restTemplate.postForObject("https://gateway.xxx.com/yao/user/login", formEntity, String.class);
            if (StringUtils.isNotBlank(post)) {
                JSONObject jsonObject = JSONObject.parseObject(post);
                if (jsonObject.getString("code").endsWith("200")) {
                    JSONObject data = jsonObject.getJSONObject("data");
                    String token = data.getString("token");
                    return token;
                }
            }
        } catch (Exception e) {
            log.error("获取token异常:{}", e);
            throw new FundException("获取token异常:" + e.getMessage());
        }
        return null;
    }

### 调用第三方SSO登录接口时出现SSL握手异常问题的解决方案 当调用第三方单点登录(SSO)接口时遇到 `javax.net.ssl.SSLHandshakeException` 和 `sun.security.validator.ValidatorException: PKIX path building failed` 的错误,通常是因为客户端无法验证服务器提供的SSL/TLS证书的有效性。以下是详细的分析和解决方案。 #### 错误原因 该错误表明Java应用程序未能找到一条有效的认证路径来验证目标站点的SSL证书。这可能是由于以下原因之一引起的: - 服务器使用的SSL证书未被Java的信任库(cacerts文件)识别。 - 服务器配置了自签名证书或中间CA未受信任。 - 客户端网络环境中的代理或其他安全设备干扰了SSL连接过程[^1]。 #### 解决方案一:导入正确的根证书到JVM信任库 如果可以获取并确认服务器所使用的是合法但尚未安装至本地JDK/JRE cacerts的信任链,则可以通过手动将其添加进来解决问题: ```bash keytool -import -alias yourAliasName -keystore $JAVA_HOME/jre/lib/security/cacerts -file server-cert.cer ``` 执行此命令前需下载对应的`.cer`格式证书文件,并替换默认密码`changeit`为实际值(视操作系统版本而定)[^1]。 #### 解决方案二:忽略SSL验证(仅用于测试) 对于开发阶段或者非生产环境中允许临时关闭HTTPS校验逻辑以便继续调试业务功能的情况,可采用如下方法实现对所有SSL请求均予以放行处理: ```java public static CloseableHttpClient createInsecureClient() { try { SSLContext sslContext = SSLContexts.custom() .loadTrustMaterial((chain, authType) -> true) // 自动接受任何证书 .build(); HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE; SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( sslContext, hostnameVerifier); return HttpClients.custom().setSSLSocketFactory(socketFactory).build(); } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) { throw new RuntimeException(e); } } ``` 注意这种方法存在严重的安全隐患,在正式部署之前务必移除此类代码片段[^2]。 #### 总结 针对上述提到的不同场景分别采取相应措施能够有效应对因SSL Handshake失败引发的各种状况。推荐优先考虑正规途径即更新信任存储而非轻易放弃安全性保障。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码码再也不用担心我的学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值