Spring RestTemplate交换帖子不支持SSL并抛出SunCertPathBuilderException

问题描述 投票:0回答:1

我正在使用restTemplate请求SSL发布。问题是我无法通过SSL向服务器发送发布请求。我正在使用自签名证书进行通信。但是,奇怪的是,当我通过SSL发送get请求时,它工作正常。

我不知道为什么POST不像GET那样不起作用。这是我使用restTemplate进行的GET和POST。

 public <T> T getByRestTemplate(String url, Object param, boolean isSSL, String token, ParameterizedTypeReference<T> responseType) throws RestClientException {
        HttpEntity<Object> requestEntity = makeHttpEntity(param, token);
        RestTemplate restTemplate = buildRestTemplate(isSSL);
        ResponseEntity<T> responseEntity;
        responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, responseType);
        return responseEntity.getBody();
    }

    public <T> T postByRestTemplate(String url, Object param, boolean isSSL, String token, Class<T> responseType) throws RestClientException {
        HttpEntity<Object> requestEntity = makeHttpEntity(param, token);
        RestTemplate restTemplate = prepareRestTemplate(isSSL);
        ResponseEntity<T> responseEntity;
        responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, responseType);
        return responseEntity.getBody();
    }

   private RestTemplate prepareRestTemplate(boolean isSSL){
        int connectTimeOut = (appConfigProperties.getConnectTimeOut()!=0)?appConfigProperties.getConnectTimeOut():5000;
        int readTimeOut = (appConfigProperties.getReadTimeOut()!=0)?appConfigProperties.getConnectTimeOut():5000;

        RestTemplate restTemplate = buildRestTemplate(isSSL);
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();

        requestFactory.setConnectTimeout(connectTimeOut);
        requestFactory.setReadTimeout(readTimeOut);
        restTemplate.setRequestFactory(requestFactory);
        return restTemplate;
    }

    private RestTemplate buildRestTemplate(boolean isSSL) {
        RestTemplate restTemplate = null;
        if (isSSL) {
            try {
                restTemplate = restTemplateSSL.restTemplateSSL();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            restTemplate = restTemplateBuilder.build();
        }

        return restTemplate;
    }

这里是与SSL设置相关的代码。

    private static TrustManager[] createTrustManagers() {
        TrustManager[] trustAllCerts;
        trustAllCerts = new TrustManager[]{new X509ExtendedTrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s){
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }

            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s, Socket socket) {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s, Socket socket) {
            }

            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) {
            }
        }};
        return trustAllCerts;
    }

 public RestTemplate restTemplateSSL() throws Exception {
        SSLContext sslContext = SSLContext.getInstance(SSL_TLS);
        sslContext.init(null, createTrustManagers(), new java.security.SecureRandom());

        SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext,
                NoopHostnameVerifier.INSTANCE);

        final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register(SSL_HTTPS, csf)
                .build();

        final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);

        CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(csf)
                .setConnectionManager(cm)
                .build();

        HttpComponentsClientHttpRequestFactory requestFactory =
                new HttpComponentsClientHttpRequestFactory();
        requestFactory.setHttpClient(httpClient);
        return new RestTemplate(requestFactory);
    }

这是我得到的日志。

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] with root cause

sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) ~[na:1.8.0_192]
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) ~[na:1.8.0_192]
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280) ~[na:1.8.0_192]
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:392) ~[na:1.8.0_192]
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302) ~[na:1.8.0_192]
    at sun.security.validator.Validator.validate(Validator.java:262) ~[na:1.8.0_192]
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324) ~[na:1.8.0_192]
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229) ~[na:1.8.0_192]
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) ~[na:1.8.0_192]
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1621) ~[na:1.8.0_192]
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223) ~[na:1.8.0_192]
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037) ~[na:1.8.0_192]
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:965) ~[na:1.8.0_192]
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064) ~[na:1.8.0_192]
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367) ~[na:1.8.0_192]
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395) ~[na:1.8.0_192]
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379) ~[na:1.8.0_192]
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:436) ~[httpclient-4.5.9.jar:4.5.9]
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:384) ~[httpclient-4.5.9.jar:4.5.9]
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142) ~[httpclient-4.5.9.jar:4.5.9]
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:374) ~[httpclient-4.5.9.jar:4.5.9]
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393) ~[httpclient-4.5.9.jar:4.5.9]
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) ~[httpclient-4.5.9.jar:4.5.9]
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186) ~[httpclient-4.5.9.jar:4.5.9]
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) ~[httpclient-4.5.9.jar:4.5.9]
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) ~[httpclient-4.5.9.jar:4.5.9]
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) ~[httpclient-4.5.9.jar:4.5.9]
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83) ~[httpclient-4.5.9.jar:4.5.9]
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56) ~[httpclient-4.5.9.jar:4.5.9]
    at org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal(HttpComponentsClientHttpRequest.java:87) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:735) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:579) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]

我已经阅读了许多其他帖子和stackoverflow问答

Access Https Rest Service using Spring RestTemplate

How to disable SSL certificate checking with Spring RestTemplate?

Disabling SSL Certificate Validation in Spring RestTemplate

https://pragmaticintegrator.wordpress.com/2017/08/13/small-hack-to-avoid-ssl-validation-in-spring-resttemplate/

以及有关此问题的更多信息。但是都没有解决。我不确定我还能怎么尝试。

spring ssl post resttemplate
1个回答
0
投票

毕竟这是一个愚蠢的错误。

设置POST请求的restClient时,我犯了一个覆盖RequestFactory的错误,因此删除了SSL连接的先前设置。

希望没有人会犯这种错误!

© www.soinside.com 2019 - 2024. All rights reserved.