programing

Spring RestTemplate로 SSL 인증서 검사를 비활성화하는 방법?

skycolor 2023. 9. 14. 21:54
반응형

Spring RestTemplate로 SSL 인증서 검사를 비활성화하는 방법?

저는 우리 테스트가 Simple을 사용하여 임베디드 HTTPS 서버를 런칭하는 통합 테스트를 작성하려고 합니다.를 사용하여 자체 서명 인증서를 만들었고 브라우저(특히 Chrome)를 사용하여 서버에 액세스할 수 있으며, 자체 서명 인증서에 대한 경고가 표시됩니다.

그러나 Spring RestTemplate를 사용하여 연결하려고 하면 ResourceAccess가 나타납니다.예외:

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을 사용하고 있습니다.

저는 이 방향으로 저를 이끄는 소스에 대한 링크가 여전히 있었으면 좋겠지만, 이것이 결국 저를 위해 작동하게 된 코드입니다.자바Doc for X509TrustManager를 검토해보면 다음과 같이 보입니다.TrustManager작업은 성공적인 검증 시 아무것도 반환하지 않고, 그렇지 않으면 예외를 부여합니다.따라서 null 구현을 사용하면 성공적인 검증으로 처리됩니다.그런 다음 다른 모든 구현을 제거합니다.

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);

위에 제시된 @Sled의 코드에 대한 약간의 개선을 위해 아래를 참조하시기 바랍니다. 그 턴-백 방식은 한 줄이 빠졌고, 지금은 제 테스트를 통과했습니다.그러면 Apache HTTP Client를 사용하도록 구성되지 않은 기본 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);
}

키 저장소를 등록할 수도 있습니다.

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);
    }
}

여기에 보안 검사가 비활성화된 솔루션이 있습니다(예: 로컬 호스트와의 대화). 또한 지금 본 솔루션 중 일부는 더 이상 사용하지 않는 메서드 등을 포함하고 있습니다.

/**
 * @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;
}

너무 늦었지만 해결책은 여기 있습니다.이 클래스를 사용하면 프로젝트의 모든 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 개체를 인스턴스화할 때 다음을 사용합니다.

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;
}
}

저는 적어도 저 자신을 위해서는 다른 답변을 바탕으로 제 코드를 공유하고 싶습니다.

// 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;:
            private static void disableSslVerification() {
            try
            {
                // Create a trust manager that does not validate certificate chains
                TrustManager[] trustAllCerts = 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) {
                    }
                }
                };

                // Install the all-trusting trust manager
                SSLContext sc = SSLContext.getInstance("SSL");
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
                HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

                // 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);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (KeyManagementException e) {
                e.printStackTrace();
            }
            }

https를 하자니 를 https 은, 을 사용해서 입니다.cert.pem에 대신에fullchain.pem요청한 서버의 인증서 파일로 지정합니다.자세한 내용은 이 스레드를 참조하십시오.

인증서 검사를 비활성화하는 것은 잘못된 해결책이며 근본적으로 안전하지 않습니다.

올바른 해결책은 자체 서명된 인증서를 트러스트 저장소로 가져오는 것입니다.훨씬 더 정확한 해결책은 CA에서 인증서에 서명하는 것입니다.

'테스트용'인 경우에도 프로덕션 구성을 테스트해야 합니다.다른 것을 테스트하는 것은 전혀 테스트가 아니라 시간 낭비일 뿐입니다.

언급URL : https://stackoverflow.com/questions/23504819/how-to-disable-ssl-certificate-checking-with-spring-resttemplate

반응형