簡體   English   中英

如何使用 Spring RestTemplate 禁用 SSL 證書檢查?

[英]How to disable SSL certificate checking with Spring RestTemplate?

我正在嘗試編寫一個集成測試,我們的測試使用Simple啟動嵌入式 HTTPS 服務器。 使用keytool創建了一個自簽名證書,並且能夠使用瀏覽器訪問服務器(特別是 Chrome,我確實收到了關於自簽名證書的警告)。

但是,當我嘗試使用Spring RestTemplate進行連接時,我得到了ResourceAccessException

org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://localhost:8088":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
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:557)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:502)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:444)
    at net.initech.DummySslServer.shouldConnect(DummySslServer.java:119)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: 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
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1917)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:301)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:295)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1369)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:156)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:925)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:860)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1043)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1343)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1371)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1355)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
    at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:78)
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:52)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:541)
    ... 33 more
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 sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
    at sun.security.validator.Validator.validate(Validator.java:260)
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1351)
    ... 47 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:145)
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
    ... 53 more

其他問題博客文章中,我看到了用類似的東西替換HostnameVerifier的建議

private static final HostnameVerifier PROMISCUOUS_VERIFIER = ( s, sslSession ) -> true;

我已經在全局和RestTemplate本身上設置了它:

HttpsURLConnection.setDefaultHostnameVerifier( PROMISCUOUS_VERIFIER );

...以及RestTemplate本身:

final RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory( new SimpleClientHttpRequestFactory() {
    @Override
    protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
        if(connection instanceof HttpsURLConnection ){
            ((HttpsURLConnection) connection).setHostnameVerifier(PROMISCUOUS_VERIFIER);
        }
        super.prepareConnection(connection, httpMethod);
    }
});

然而,我仍然收到上述錯誤。 我怎樣才能繞過它?

  1. 在單元測試之外本地安裝證書不是一種選擇,因為它需要在每台開發機器和構建服務器上手動安裝,並且會導致大量繁文縟節。
  2. 我們需要 SSL 因為我們正在測試位於RestTemplate之上的庫並且我們正在正確配置它。

我正在使用 Java 8(但可以使用 7)和 Spring 4.0.3。

我希望我仍然有一個指向這個方向的源代碼的鏈接,但這是最終為我工作的代碼。 通過查看X509TrustManager的 JavaDoc,看起來TrustManager的工作方式是在成功驗證時不返回任何內容,否則拋出異常。 因此,對於null implementation ,它被視為成功的驗證。 然后刪除所有其他實現。

import javax.net.ssl.*;
import java.security.*;
import java.security.cert.X509Certificate;

public final class SSLUtil{

    private static final TrustManager[] UNQUESTIONING_TRUST_MANAGER = new TrustManager[]{
            new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers(){
                    return null;
                }
                public void checkClientTrusted( X509Certificate[] certs, String authType ){}
                public void checkServerTrusted( X509Certificate[] certs, String authType ){}
            }
        };

    public  static void turnOffSslChecking() throws NoSuchAlgorithmException, KeyManagementException {
        // Install the all-trusting trust manager
        final SSLContext sc = SSLContext.getInstance("SSL");
        sc.init( null, UNQUESTIONING_TRUST_MANAGER, null );
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }

    public static void turnOnSslChecking() throws KeyManagementException, NoSuchAlgorithmException {
        // Return it to the initial state (discovered by reflection, now hardcoded)
        SSLContext.getInstance("SSL").init( null, null, null );
    }

    private SSLUtil(){
        throw new UnsupportedOperationException( "Do not instantiate libraries.");
    }
}

為了找到這個問題並需要另一個不僅適合單元測試的解決方案的其他開發人員:

我在博客上找到了這個(不是我的解決方案!感謝博客所有者)。

TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;

SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
        .loadTrustMaterial(null, acceptingTrustStrategy)
        .build();

SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);

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

HttpComponentsClientHttpRequestFactory requestFactory =
        new HttpComponentsClientHttpRequestFactory();

requestFactory.setHttpClient(httpClient);

RestTemplate restTemplate = new RestTemplate(requestFactory);

您還可以注冊您的密鑰庫:

private void registerKeyStore(String keyStoreName) {
    try {
        ClassLoader classLoader = this.getClass().getClassLoader();
        InputStream keyStoreInputStream = classLoader.getResourceAsStream(keyStoreName);
        if (keyStoreInputStream == null) {
            throw new FileNotFoundException("Could not find file named '" + keyStoreName + "' in the CLASSPATH");
        }

        //load the keystore
        KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
        keystore.load(keyStoreInputStream, null);

        //add to known keystore 
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keystore);

        //default SSL connections are initialized with the keystore above
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustManagers, null);
        SSLContext.setDefault(sc);
    } catch (IOException | GeneralSecurityException e) {
        throw new RuntimeException(e);
    }
}

請參閱下面對上面顯示的@Sled 代碼的適度改進,該開啟方法缺少一行,現在它通過了我的測試。 在使用默認 HTTP 配置(未配置為使用 Apache HTTP 客戶端)的 Spring-Boot 版本 2 應用程序中使用 RestTemplate 時,這將禁用 HTTPS 證書和主機名欺騙。

package org.my.little.spring-boot-v2.app;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

/**
 * Disables and enables certificate and host-name checking in
 * HttpsURLConnection, the default JVM implementation of the HTTPS/TLS protocol.
 * Has no effect on implementations such as Apache Http Client, Ok Http.
*/
public final class SSLUtils {

    private static final HostnameVerifier jvmHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();

    private static final HostnameVerifier trivialHostnameVerifier = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession sslSession) {
            return true;
        }
    };

    private static final TrustManager[] UNQUESTIONING_TRUST_MANAGER = new TrustManager[] { new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public void checkClientTrusted(X509Certificate[] certs, String authType) {
        }

        public void checkServerTrusted(X509Certificate[] certs, String authType) {
        }
    } };

    public static void turnOffSslChecking() throws NoSuchAlgorithmException, KeyManagementException {
        HttpsURLConnection.setDefaultHostnameVerifier(trivialHostnameVerifier);
        // Install the all-trusting trust manager
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, UNQUESTIONING_TRUST_MANAGER, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }

    public static void turnOnSslChecking() throws KeyManagementException, NoSuchAlgorithmException {
        HttpsURLConnection.setDefaultHostnameVerifier(jvmHostnameVerifier);
        // Return it to the initial state (discovered by reflection, now hardcoded)
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, null, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }

    private SSLUtils() {
        throw new UnsupportedOperationException("Do not instantiate libraries.");
    }
}
@Bean(name = "restTemplateByPassSSL")
public RestTemplate restTemplateByPassSSL()
        throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
    TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
    HostnameVerifier hostnameVerifier = (s, sslSession) -> true;
    SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
    SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
    CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();
    HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
    requestFactory.setHttpClient(httpClient);

    return new RestTemplate(requestFactory);
}

這是禁用安全檢查的解決方案(例如,與本地主機對話)此外,我現在看到的一些解決方案包含不推薦使用的方法等。

/**
 * @param configFilePath
 * @param ipAddress
 * @param userId
 * @param password
 * @throws MalformedURLException
 */
public Upgrade(String aConfigFilePath, String ipAddress, String userId, String password) {
    configFilePath = aConfigFilePath;
    baseUri = "https://" + ipAddress + ":" + PORT + "/";

    restTemplate = new RestTemplate(createSecureTransport(userId, password, ipAddress, PORT));
    restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
    restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
 }

ClientHttpRequestFactory createSecureTransport(String username,
        String password, String host, int port) {
    HostnameVerifier nullHostnameVerifier = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };
    UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password);
    CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    credentialsProvider.setCredentials(
            new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM), credentials);

    HttpClient client = HttpClientBuilder.create()
            .setSSLHostnameVerifier(nullHostnameVerifier)
            .setSSLContext(createContext())
            .setDefaultCredentialsProvider(credentialsProvider).build();

    HttpComponentsClientHttpRequestFactory requestFactory = 
            new HttpComponentsClientHttpRequestFactory(client);

    return requestFactory;
}

private SSLContext createContext() {
    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
        }

        public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
        }
    } };

    try {
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, null);
        SSLContext.setDefault(sc);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
        return sc;

    } catch (Exception e) {
    }
    return null;
}

太晚了,但在這里你有我的解決方案。 使用這個 class 你可以關閉你項目中的所有 ssl 驗證。

import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;


@Slf4j
@Component
public class SslWarningRemover {

    public SslWarningRemover() {
        log.info("Disabling SSL warning...");
        try {
            TrustManager[] trustAllCerts = new TrustManager[] {
                    new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }
                        
                        public void checkClientTrusted(X509Certificate[] certs, String authType) {
                            
                        }
                        
                        public void checkServerTrusted(X509Certificate[] certs, String authType) {
                            
                        }
                    }
            };
            
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
            
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
            
            log.info("SSL verification disabled");
        } catch (Exception e) {
            log.error("Error while trying to disable SSL verification: " + e.getMessage(), e);
        }
        
        log.info("SSL warning process remover has finished!");
    }
}

如果你想在單個 RestTemplate 中禁用 SSL 驗證,試試這個:

import java.io.IOException;
import java.net.HttpURLConnection;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import lombok.extern.slf4j.Slf4j;


@Slf4j
public class CustomClientHttpRequestFactory extends SimpleClientHttpRequestFactory {
    
    private static final HostnameVerifier PROMISCUOUS_VERIFIER = new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };
    
    private static final TrustManager[] ALL_CERT_TRUST_MANAGER = new TrustManager[] {
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                
                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                    
                }
                
                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                    
                }
            }
    };
    
    private static SSLContext ALL_CERT_TRUST_SSLCONTEXT = null;
    
    static {
        try {
            ALL_CERT_TRUST_SSLCONTEXT = SSLContext.getInstance("SSL");
            ALL_CERT_TRUST_SSLCONTEXT.init(null, ALL_CERT_TRUST_MANAGER, new SecureRandom());
        } catch (Exception e) {
            log.error("Error disabling SSL verification");
            log.error(e.getMessage(), e);
        }
    }
    
    
    private boolean disableSslVerification = false;
    
    public CustomClientHttpRequestFactory(int connectTimeout, int readTimeout, boolean disableSslVerification) {
        this.setConnectTimeout(connectTimeout);
        this.setReadTimeout(readTimeout);
        this.disableSslVerification = disableSslVerification;
    }
    
    @Override
    protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
        if (disableSslVerification && ALL_CERT_TRUST_SSLCONTEXT != null && connection instanceof HttpsURLConnection) {
            ((HttpsURLConnection) connection).setHostnameVerifier(PROMISCUOUS_VERIFIER);
            ((HttpsURLConnection) connection).setSSLSocketFactory(ALL_CERT_TRUST_SSLCONTEXT.getSocketFactory());
        }
        super.prepareConnection(connection, httpMethod);
    }
    
}

然后,當您實例化 RestTemplate object 時,請使用:

RestTemplate restTemplate = new RestTemplate(new CustomClientHttpRequestFactory(connectTimeout, readTimeout, disableSslVerification));

disableSslVerification參數為true

我知道回答太老了,但我找不到這樣的解決方案。

與球衣客戶一起為我工作的代碼:

import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;

import javax.net.ssl.*;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedHashMap;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;

public class Testi {

static {
    disableSslVerification();
}
private static void disableSslVerification() {
    // Create all-trusting host name verifier
    HostnameVerifier allHostsValid = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };
    // Install the all-trusting host verifier
    HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
}

public Testi() {
    MultivaluedHashMap<String, Object> headers = new MultivaluedHashMap<>();
    //... initialize headers

    Form form = new Form();
    Entity<Form> entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE);
    // initialize entity ...

    WebTarget target = getWebTarget();
    Object responseResult = target.path("api/test/path...").request()
            .headers(headers).post(entity, Object.class);

}

public static void main(String args[]) {
    new Testi();
}

private WebTarget getWebTarget() {
    ClientConfig clientConfig = new ClientConfig();
    clientConfig.property(ClientProperties.CONNECT_TIMEOUT, 30000);
    clientConfig.property(ClientProperties.READ_TIMEOUT, 30000);

    SSLContext sc = getSSLContext();
    Client client = ClientBuilder.newBuilder().sslContext(sc).withConfig(clientConfig).build();
    WebTarget target = client.target("...url...");
    return target;
}

private SSLContext getSSLContext() {
    try {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
            @Override
            public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws CertificateException {

            }

            @Override
            public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws CertificateException {

            }

            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        }
        };

        // Install the all-trusting trust manager
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        return sc;
    } catch (NoSuchAlgorithmException | KeyManagementException e) {
        e.printStackTrace();
    }
    return null;
}
}

在我的情況下,使用letsencrypt https,這是由於使用cert.pem而不是fullchain.pem作為請求服務器上的證書文件造成的。 有關詳細信息,請參閱此線程

我想至少為我自己分享我基於其他答案的代碼。

// Spring Boot 2.7.5 / Java 11
@PostConstruct
private void onPostConstruct() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
    // http://www.chrispad.com/2019/02/disable-certificate-verification-using.html
    var sslContext = SSLContexts.custom().loadTrustMaterial((c, at) -> true).build();
    var socketFactory = new SSLConnectionSocketFactory(sslContext, (h, s) -> true);
    var httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory).build();
    var requestFactory = new HttpComponentsClientHttpRequestFactory();
    requestFactory.setHttpClient(httpClient);
    template = templateBuilder.requestFactory(() -> requestFactory).build();
}

private final RestTemplateBuilder templateBuilder;

private RestTemplate template;:

禁用證書檢查是錯誤的解決方案,而且非常不安全。

正確的解決方案是將自簽名證書導入您的信任庫。 更正確的解決方案是讓 CA 簽署證書。

如果這“僅用於測試”,則仍然需要測試生產配置。 測試其他東西根本不是測試,它只是浪費時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM