Apache HttpClient 4.0에서 SSL 인증서 오류를 무시하는 방법


125

Apache HttpClient 4.0에서 유효하지 않은 SSL 인증서 오류를 어떻게 우회 합니까?


12
이 질문에 대한 답변은 요청 된 것 이상을 수행하지 않습니다 : 그들은 오류를 무시하게하지만 근본적인 문제를 해결하지는 않습니다 (화재를 피우는 대신 연기 경보에서 배터리를 제거하는 것과 약간 같음) ). 인증서는 SSL / TLS 연결의 보안을 유지하는 데 목적이 있으며 이러한 오류를 무시하면 MITM 공격에 취약성이 있습니다. 오류를 무시하는 대신 테스트 인증서를 사용하십시오.
Bruno


46
"연기 경보에서 배터리를 제거하는 것과 같이"다른 개발자에게 의심의 혜택을주고 그들이하는 일을 알고 있다고 가정 할 수 있습니다. 이 질문에 대한 동기는 아마도 로컬 테스트이며 OP는 간단한 SSL 환경을 설정하는 데 필요한 끔찍한 Java 상용구를 거치지 않고 빠른 테스트를 실행하기를 원합니다. 어쩌면 누군가는 "너보다 더 성가신"강의에 들어 가지 않고 질문에 대답 할 수있을 것입니다.
Mike

즉, 회사 내부 JIRA 서버에는 도메인에 포함 된 Windows 시스템에서는 유효하고 다른 시스템에서는 유효하지 않은 "Windows 보안 정책 기반 인증"이 있습니다. 이 정책을 제어 할 수없고 여전히 JIRA REST API를 호출하려고합니다.
odiszapc

1
@Bruno 작은 부엌 화재를 처리하는 동안 30-60 분 동안 연기 탐지기를 비활성화 할 수 없다는 것은 일부 법률 공무원이 범죄에 대한 경계를 느낀 시점에 사용 패턴에 대한 통찰력이 부족하다는 것을 보여줍니다. "연기 경보에서 배터리 제거"라는 개념이 있다는 사실이이를 증명합니다. 보안에 영향을 미치지 않는 간단한 테스트를 위해 인증서를 작동시켜야하는 것에 대해 같은 수준의 분노를 느낍니다. 이 질문의 존재는 이것을 증명합니다.
Bill K

답변:


84

자신의 TrustManager를 사용하여 SSLContext를 작성하고이 컨텍스트를 사용하여 HTTPS 체계를 작성해야합니다. 코드는 다음과 같습니다.

SSLContext sslContext = SSLContext.getInstance("SSL");

// set up a TrustManager that trusts everything
sslContext.init(null, new TrustManager[] { new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                    System.out.println("getAcceptedIssuers =============");
                    return null;
            }

            public void checkClientTrusted(X509Certificate[] certs,
                            String authType) {
                    System.out.println("checkClientTrusted =============");
            }

            public void checkServerTrusted(X509Certificate[] certs,
                            String authType) {
                    System.out.println("checkServerTrusted =============");
            }
} }, new SecureRandom());

SSLSocketFactory sf = new SSLSocketFactory(sslContext);
Scheme httpsScheme = new Scheme("https", 443, sf);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(httpsScheme);

// apache HttpClient version >4.2 should use BasicClientConnectionManager
ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry);
HttpClient httpClient = new DefaultHttpClient(cm);

1
내 사이트에 유효한 SSL 인증서를 구매하지 않고 사용하고 싶다고 말하면이 코드가 도움이 될 수 있습니까? URL이 필요하거나 예외 처리가 필요한 부분이 보이지 않는 이유는 무엇입니까?
Viet

19
흠, 그것은 '새로운 SSLSocketFactory (ssslCont)'가 SSLContext가 아닌 KeyStore를 기대하고 있다는 것을 말해줍니다. 뭔가 빠졌습니까?
MSpeed

2
X509TrustManager를 TrustManager로 캐스트 할 수 없다는 오류가 발생합니다.
MW.

2
올바른 패키지 (예 : org.apache.http)를 가져와야합니다.
warden

2
누구나이 모든 것을 함께 사용하는 방법을 알고 HttpClientBuilder있습니까?
Ali

112

다른 모든 답변은 더 이상 사용되지 않거나 HttpClient 4.3에서 작동하지 않았습니다.

http 클라이언트를 빌드 할 때 모든 호스트 이름을 허용하는 방법은 다음과 같습니다.

CloseableHttpClient httpClient = HttpClients
    .custom()
    .setHostnameVerifier(AllowAllHostnameVerifier.INSTANCE)
    .build();

또는 버전 4.4 이상을 사용중인 경우 업데이트 된 호출은 다음과 같습니다.

CloseableHttpClient httpClient = HttpClients
    .custom()
    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
    .build();

답변에 감사드립니다. Android compile ( "org.apache.httpcomponents : httpclient : 4.3.4")에서 사용중인 HttpsClients 패키지를 알고 싶지만이 클래스는 표시되지 않습니다.
Juan Saravia

1
패키지는 org.apache.http.impl.client.HttpClients입니다.
erversteeg

14
이것은 호스트 이름 불일치 문제를 해결하지만 (신뢰할 수 있음) 인증서가 신뢰할 수있는 기관에 의해 서명되지 않은 경우 작동하지 않는 것 같습니다.
twm

1
@twm 그렇기 때문에 "모든 호스트 이름을 허용"하고 신뢰 문제에는 다른 구성이 필요합니다.
eis

1
@ eis, 나는이 답변이 어떤 경우에는 원래 질문을 다루고 다른 것은 아니라고 지적했습니다.
twm

43

최신 HttpClient 4.5 로이 작업을 수행해야 했으며 4.4 이후 몇 가지를 더 이상 사용하지 않는 것처럼 보이므로 여기에 나와 가장 최근의 API를 사용하는 스 니펫이 있습니다.

final SSLContext sslContext = new SSLContextBuilder()
        .loadTrustMaterial(null, (x509CertChain, authType) -> true)
        .build();

return HttpClientBuilder.create()
        .setSSLContext(sslContext)
        .setConnectionManager(
                new PoolingHttpClientConnectionManager(
                        RegistryBuilder.<ConnectionSocketFactory>create()
                                .register("http", PlainConnectionSocketFactory.INSTANCE)
                                .register("https", new SSLConnectionSocketFactory(sslContext,
                                        NoopHostnameVerifier.INSTANCE))
                                .build()
                ))
        .build();

HttpClient를 4.5.2를 위해 또한 나를 위해 일한
카스 란잔

이 하나가 최신입니다 HttpClient를 4.5
넌 멋진

31

레코드의 경우 HttpClient 4.1을 사용하여 훨씬 간단하게 수행 할 수 있습니다

    SSLSocketFactory sslsf = new SSLSocketFactory(new TrustStrategy() {

        public boolean isTrusted(
                final X509Certificate[] chain, String authType) throws CertificateException {
            // Oh, I am easy...
            return true;
        }

    });

1
이 샘플에서 일부 코드가 누락 되었습니까? 아마도 httpClient.set에 대한 호출 ...?
그레이

6
httpclient.getConnectionManager (). getSchemeRegistry (). register (new Scheme ( "https", 443, sslsf));
Ben Flynn

8
SSLSocketFactory는 HttpClient 4.3에서 사용되지 않습니다
Toilal

1
Java 8을 사용한다면new SSLSocketFactory((chain, authType) -> true);
jlb

28

아파치 HttpClient 4.5.5

HttpClient httpClient = HttpClients
            .custom()
            .setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, TrustAllStrategy.INSTANCE).build())
            .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
            .build();

더 이상 사용되지 않는 API가 사용되지 않았습니다.

검증 가능한 간단한 테스트 사례 :

package org.apache.http.client.test;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

public class ApacheHttpClientTest {

    private HttpClient httpClient;

    @Before
    public void initClient() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
        httpClient = HttpClients
                .custom()
                .setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, TrustAllStrategy.INSTANCE).build())
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                .build();
    }

    @Test
    public void apacheHttpClient455Test() throws IOException {
        executeRequestAndVerifyStatusIsOk("https://expired.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://wrong.host.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://self-signed.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://untrusted-root.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://revoked.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://pinning-test.badssl.com");
        executeRequestAndVerifyStatusIsOk("https://sha1-intermediate.badssl.com");
    }

    private void executeRequestAndVerifyStatusIsOk(String url) throws IOException {
        HttpUriRequest request = new HttpGet(url);

        HttpResponse response = httpClient.execute(request);
        int statusCode = response.getStatusLine().getStatusCode();

        assert statusCode == 200;
    }
}

감사합니다! 그냥 변경 TrustAllStrategy.INSTANCE으로 TrustSelfSignedStrategy.INSTANCE이 대답한다.
퍼시 베가

이것은 나를 위해 작동하지 않았습니다. javax.net.ssl.SSLHandshakeException : sun.security.validator.ValidatorException : PKIX 경로 작성 실패 : sun.security. provider.certpath.SunCertPathBuilderException : 요청한 대상에 대한 유효한 인증 경로를 찾을 수 없음
ggb667

26

기록을 위해 httpclient 4.3.6으로 테스트했으며 유창한 API의 Executor와 호환됩니다.

CloseableHttpClient httpClient = HttpClients.custom().
                    setHostnameVerifier(new AllowAllHostnameVerifier()).
                    setSslcontext(new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy()
                    {
                        public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
                        {
                            return true;
                        }
                    }).build()).build();

3
HttpClient를 4.4를 들어 위쪽으로, 당신은이 작업을 수행 - 그리고 또한 작성해야 할 수도 있습니다 SSLConnectionSocketFactory그것을 사용을 SSLContext하고,이 정의 Registry<ConnectionSocketFactory>당신이를 만들려고하는 경우에, PoolingHttpClientConnectionManager. 다른 답변은 더 인기가 있지만 HttpClient 4.4에서는 작동하지 않습니다.
Thomas W

1
httpclient-4.3.5.jar에서 이와 똑같이 작동합니다.
Harald

18

Apache HttpClient 4.4의 경우 :

HttpClientBuilder b = HttpClientBuilder.create();

SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
    public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
        return true;
    }
}).build();
b.setSslcontext( sslContext);

// or SSLConnectionSocketFactory.getDefaultHostnameVerifier(), if you don't want to weaken
HostnameVerifier hostnameVerifier = SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", PlainConnectionSocketFactory.getSocketFactory())
        .register("https", sslSocketFactory)
        .build();

// allows multi-threaded use
PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager( socketFactoryRegistry);
b.setConnectionManager( connMgr);

HttpClient client = b.build();

이것은 실제 작업 구현에서 추출됩니다.

다른 답변은 인기가 있지만 HttpClient 4.4의 경우 작동하지 않습니다. 나는 시간을 소비하고 가능성을 소진했지만 4.4에서 API 변경 및 재배치가 극도로 큰 것으로 보입니다.

http://literatejava.com/networks/ignore-ssl-certificate-errors-apache-httpclient-4-4/ 에서 약간 더 자세한 설명을 참조하십시오.

희망이 도움이됩니다!


2
내가 필요한 SSLContext 비트였습니다. 너무 많은 의무.
muttonUp

14

유효하지 않은 호스트 이름 오류를 제거하기 만하면됩니다.

HttpClient httpClient = new DefaultHttpClient();
SSLSocketFactory sf = (SSLSocketFactory)httpClient.getConnectionManager()
    .getSchemeRegistry().getScheme("https").getSocketFactory();
sf.setHostnameVerifier(new AllowAllHostnameVerifier());

8
sf.setHostnameVerifier 메소드는 4.1부터 더 이상 사용되지 않습니다. 대안은 생성자 중 하나를 사용하는 것입니다. 예를 들면 :SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
kaliatech

레거시 코드를 처리해야 할 때 매우 유용했습니다.
DuncanSungWKim

9

우리는 HTTPClient 4.3.5를 사용하고 있으며 거의 ​​모든 솔루션이 stackoverflow에 존재하지만 아무것도 시도하지 않았습니다. 문제를 생각하고 알아 낸 후에는 완벽하게 작동하는 다음 코드가 나오고 HttpClient 인스턴스를 만들기 전에 추가하십시오.

게시물 요청을 할 때 호출 할 메소드 ...

SSLContextBuilder builder = new SSLContextBuilder();
    builder.loadTrustMaterial(null, new TrustStrategy() {
        @Override
        public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            return true;
        }
    });

    SSLConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(builder.build(),
            SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

    HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslSF).build();
    HttpPost postRequest = new HttpPost(url);

정상적인 형태로 귀하의 요청을 계속하십시오


7

유창한 4.5.2에서는 작동하도록 다음과 같이 수정해야했습니다.

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

    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new SecureRandom());
    CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).setSslcontext(sc).build();

    String output = Executor.newInstance(httpClient).execute(Request.Get("https://127.0.0.1:3000/something")
                                      .connectTimeout(1000)
                                      .socketTimeout(1000)).returnContent().asString();
    } catch (Exception e) {
    }

1
이것은 나를 위해 일한 유일한 솔루션입니다. 4.5로 업그레이드하고 시도하기 전에 4.3 및 4.4에 대한 위의 솔루션을 시도했습니다.
dirkoneill

6

이것이 내가 한 방법입니다-

  1. 나만의 MockSSLSocketFactory를 생성하십시오 (아래 첨부 된 클래스)
  2. DefaultHttpClient를 초기화하는 데 사용하십시오. 프록시를 사용하는 경우 프록시 설정을 제공해야합니다.

DefaultHTTPClient 초기화-

SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
    schemeRegistry.register(new Scheme("https", 443, new MockSSLSocketFactory()));
    ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry);

    DefaultHttpClient httpclient = new DefaultHttpClient(cm);

모의 SSL 공장-

public class MockSSLSocketFactory extends SSLSocketFactory {

public MockSSLSocketFactory() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
    super(trustStrategy, hostnameVerifier);
}

private static final X509HostnameVerifier hostnameVerifier = new X509HostnameVerifier() {
    @Override
    public void verify(String host, SSLSocket ssl) throws IOException {
        // Do nothing
    }

    @Override
    public void verify(String host, X509Certificate cert) throws SSLException {
        //Do nothing
    }

    @Override
    public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
        //Do nothing
    }

    @Override
    public boolean verify(String s, SSLSession sslSession) {
        return true; 
    }
};

private static final TrustStrategy trustStrategy = new TrustStrategy() {
    @Override
    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        return true;
    }
};
}

프록시 뒤에있는 경우이 작업을 수행해야합니다-

HttpParams params = new BasicHttpParams();
    params.setParameter(AuthPNames.PROXY_AUTH_PREF, getClientAuthPrefs());

DefaultHttpClient httpclient = new DefaultHttpClient(cm, params);

httpclient.getCredentialsProvider().setCredentials(
                        new AuthScope(proxyHost, proxyPort),
                        new UsernamePasswordCredentials(proxyUser, proxyPass));

앞으로 수입품을 포함 시키면 도움이 될 것입니다. 두 가지 다른 클래스가 있습니다.
AndroidDev

4

에 확장에 ZZ 코더의 대답 이 설정되어있는 HostnameVerifier를 오버라이드 (override) 좋을 것입니다.

// ...
SSLSocketFactory sf = new SSLSocketFactory (sslContext);
sf.setHostnameVerifier(new X509HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }

    public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
    }

    public void verify(String host, X509Certificate cert) throws SSLException {
    }

    public void verify(String host, SSLSocket ssl) throws IOException {
    }
});
// ...

당신은 수행하여 동일한을 달성 할 수있다sf.setHostnameVerifier(new AllowAllHostnameVerifier());
댄 다이어를

7
sf.setHostnameVerifier는 4.1부터 사용되지 않습니다. 대안은 생성자 중 하나를 사용하는 것입니다. 예를 들면 :SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
kaliatech

4
        DefaultHttpClient httpclient = new DefaultHttpClient();

    SSLContext sslContext;
    try {
        sslContext = SSLContext.getInstance("SSL");

        // set up a TrustManager that trusts everything
        try {
            sslContext.init(null,
                    new TrustManager[] { new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() {
                            log.debug("getAcceptedIssuers =============");
                            return null;
                        }

                        public void checkClientTrusted(
                                X509Certificate[] certs, String authType) {
                            log.debug("checkClientTrusted =============");
                        }

                        public void checkServerTrusted(
                                X509Certificate[] certs, String authType) {
                            log.debug("checkServerTrusted =============");
                        }
                    } }, new SecureRandom());
        } catch (KeyManagementException e) {
        }
         SSLSocketFactory ssf = new SSLSocketFactory(sslContext,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
         ClientConnectionManager ccm = this.httpclient.getConnectionManager();
         SchemeRegistry sr = ccm.getSchemeRegistry();
         sr.register(new Scheme("https", 443, ssf));            
    } catch (Exception e) {
        log.error(e.getMessage(),e);
    }

4

HttpClient 4.4.x의 모든 인증서를 승인하려면 httpClient를 작성할 때 다음 하나의 라이너를 사용할 수 있습니다.

httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).setSslcontext(new SSLContextBuilder().loadTrustMaterial(null, (x509Certificates, s) -> true).build()).build();

이 문제가 발생합니다. 원인 : javax.net.ssl.SSLHandshakeException : java.security.cert.CertificateException : 주제 대체 이름이 없습니까?

HttpClient API 또는 RestClient API에서 인증서없이 SSL 사이트에 연결하는 방법은 무엇입니까?

4

Fluent API를 사용하여 HttpClient 4.5.5로 테스트

final SSLContext sslContext = new SSLContextBuilder()
    .loadTrustMaterial(null, (x509CertChain, authType) -> true).build();

CloseableHttpClient httpClient = HttpClients.custom()
    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
    .setSSLContext(sslContext).build();

String result = Executor.newInstance(httpClient)
    .execute(Request.Get("https://localhost:8080/someapi")
    .connectTimeout(1000).socketTimeout(1000))
    .returnContent().asString();

3

아래 코드는 4.5.5

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

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

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

class HttpsSSLClient {


    public static CloseableHttpClient createSSLInsecureClient() {
        SSLContext sslcontext = createSSLContext();
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new HostnameVerifier() {

            @Override
            public boolean verify(String paramString, SSLSession paramSSLSession) {
                return true;
            }
        });
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        return httpclient;
    }


    private static SSLContext createSSLContext() {
        SSLContext sslcontext = null;
        try {
            sslcontext = SSLContext.getInstance("TLS");
            sslcontext.init(null, new TrustManager[] {new TrustAnyTrustManager()}, new SecureRandom());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return sslcontext;
    }


    private static class TrustAnyTrustManager implements X509TrustManager {

        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

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

}
public class TestMe {


    public static void main(String[] args) throws IOException {
        CloseableHttpClient client = HttpsSSLClient.createSSLInsecureClient();

        CloseableHttpResponse res = client.execute(new HttpGet("https://wrong.host.badssl.com/"));
        System.out.println(EntityUtils.toString(res.getEntity()));
    }
}

코드의 출력은

암호

브라우저 출력

잘못된 SSL

사용 된 찌꺼기는 아래에 있습니다

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tarun</groupId>
    <artifactId>testing</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>6</source>
                    <target>6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
    <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.5</version>
    </dependency>

</dependencies>
</project>

업데이트 된 답변에 감사드립니다, 나는 새로운 사람에게 현상금을 "환영"으로 수여했지만 모두에게 업데이트 된 답변을 원했습니다!

1
@feelingunwelcome, 물론입니다. 나는 또한 그를
찬성했다

2

Apache HttpClient 4.1.3의 전체 작동 버전 (위의 oleg 코드를 기반으로하지만 여전히 내 시스템에는 allow_all_hostname_verifier가 필요했습니다) :

private static HttpClient trustEveryoneSslHttpClient() {
    try {
        SchemeRegistry registry = new SchemeRegistry();

        SSLSocketFactory socketFactory = new SSLSocketFactory(new TrustStrategy() {

            public boolean isTrusted(final X509Certificate[] chain, String authType) throws CertificateException {
                // Oh, I am easy...
                return true;
            }

        }, org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        registry.register(new Scheme("https", 443, socketFactory));
        ThreadSafeClientConnManager mgr = new ThreadSafeClientConnManager(registry);
        DefaultHttpClient client = new DefaultHttpClient(mgr, new DefaultHttpClient().getParams());
        return client;
    } catch (GeneralSecurityException e) {
        throw new RuntimeException(e);
    }
}

참고 실제 시스템에서이 중 하나라도 실패하면 실제로 할 수있는 것이 많지 않기 때문에 모든 예외를 다시 발생시킵니다.


2

유창한 API를 사용하는 경우 다음을 통해 API 를 설정해야합니다 Executor.

Executor.unregisterScheme("https");
SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslContext,
                                  SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Executor.registerScheme(new Scheme("https", 443, sslSocketFactory));

... 여기서 ZZ 코더 의 답변에 sslContext표시된대로 SSLContext가 작성됩니다 .

그런 다음 http 요청을 다음과 같이 수행 할 수 있습니다.

String responseAsString = Request.Get("https://192.168.1.0/whatever.json")
                         .execute().getContent().asString();

참고 : HttpClient 4.2로 테스트


불행히도 4.3에서 더 이상 사용되지 않습니다. "더 이상 사용되지 않습니다. (4.3) 사용하지 마십시오."
STM

2

4.3.3으로 테스트

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class AccessProtectedResource {

public static void main(String[] args) throws Exception {

    // Trust all certs
    SSLContext sslcontext = buildSSLContext();

    // Allow TLSv1 protocol only
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslcontext,
            new String[] { "TLSv1" },
            null,
            SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

    CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(sslsf)
            .build();
    try {

        HttpGet httpget = new HttpGet("https://yoururl");

        System.out.println("executing request" + httpget.getRequestLine());

        CloseableHttpResponse response = httpclient.execute(httpget);
        try {
            HttpEntity entity = response.getEntity();

            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            if (entity != null) {
                System.out.println("Response content length: " + entity.getContentLength());
            }
            for (Header header : response.getAllHeaders()) {
                System.out.println(header);
            }
            EntityUtils.consume(entity);
        } finally {
            response.close();
        }
    } finally {
        httpclient.close();
    }
}

private static SSLContext buildSSLContext()
        throws NoSuchAlgorithmException, KeyManagementException,
        KeyStoreException {
    SSLContext sslcontext = SSLContexts.custom()
            .setSecureRandom(new SecureRandom())
            .loadTrustMaterial(null, new TrustStrategy() {

                public boolean isTrusted(X509Certificate[] chain, String authType)
                        throws CertificateException {
                    return true;
                }
            })
            .build();
    return sslcontext;
}

}


원하는 경우 헤더에 값을 설정하는 방법은 무엇입니까?

2

4.5.4에서 테스트 :

            SSLContext sslContext = new SSLContextBuilder()
                    .loadTrustMaterial(null, (TrustStrategy) (arg0, arg1) -> true).build();

            CloseableHttpClient httpClient = HttpClients
                    .custom()
                    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                    .setSSLContext(sslContext)
                    .build();

0

Apache HttpClient 4.1을 포함하는 AmazonS3Client를 사용할 때이 문제가 발생하면 SSL 인증서 검사기가 완화되도록 다음과 같은 시스템 속성을 정의하기 만하면됩니다.

-Dcom.amazonaws.sdk.disableCertChecking = true

장난 관리


0

fwiw, JAX-RS 2.x의 "RestEasy"구현을 사용하여 특수한 "trust all"클라이언트를 빌드하는 예제

    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.security.GeneralSecurityException;
    import java.security.KeyManagementException;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import java.util.ArrayList;
    import java.util.Arrays;
    import javax.ejb.Stateless;
    import javax.net.ssl.SSLContext;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import javax.ws.rs.client.Entity;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.Response;
    import org.apache.http.config.Registry;
    import org.apache.http.config.RegistryBuilder;
    import org.apache.http.conn.HttpClientConnectionManager;
    import org.apache.http.conn.ssl.TrustStrategy;
    import org.jboss.resteasy.client.jaxrs.ResteasyClient;
    import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
    import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
    import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine;
    import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
    import org.apache.http.conn.socket.ConnectionSocketFactory;
    import org.apache.http.conn.ssl.NoopHostnameVerifier;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClientBuilder;
    import org.apache.http.ssl.SSLContexts;

    @Stateless
    @Path("/postservice")
    public class PostService {

        private static final Logger LOG = LogManager.getLogger("PostService");

        public PostService() {
        }

        @GET
        @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
        public PostRespDTO get() throws NoSuchAlgorithmException, KeyManagementException, MalformedURLException, IOException, GeneralSecurityException {

            //...object passed to the POST method...
            PostDTO requestObject = new PostDTO();
            requestObject.setEntryAList(new ArrayList<>(Arrays.asList("ITEM0000A", "ITEM0000B", "ITEM0000C")));
            requestObject.setEntryBList(new ArrayList<>(Arrays.asList("AAA", "BBB", "CCC")));

            //...build special "trust all" client to call POST method...
            ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(createTrustAllClient());

            ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
            ResteasyWebTarget target = client.target("https://localhost:7002/postRespWS").path("postrespservice");
            Response response = target.request().accept(MediaType.APPLICATION_JSON).post(Entity.entity(requestObject, MediaType.APPLICATION_JSON));

            //...object returned from the POST method...
            PostRespDTO responseObject = response.readEntity(PostRespDTO.class);

            response.close();

            return responseObject;
        }


        //...get special "trust all" client...
        private static CloseableHttpClient createTrustAllClient() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {

            SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, TRUSTALLCERTS).useProtocol("TLS").build();
            HttpClientBuilder builder = HttpClientBuilder.create();
            NoopHostnameVerifier noop = new NoopHostnameVerifier();
            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, noop);
            builder.setSSLSocketFactory(sslConnectionSocketFactory);
            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register("https", sslConnectionSocketFactory).build();
            HttpClientConnectionManager ccm = new BasicHttpClientConnectionManager(registry);
            builder.setConnectionManager(ccm);

            return builder.build();
        }


        private static final TrustStrategy TRUSTALLCERTS = new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
                return true;
            }
        };
    }

관련 Maven 종속성

    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-client</artifactId>
        <version>3.0.10.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>jaxrs-api</artifactId>
        <version>3.0.10.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jackson2-provider</artifactId>
        <version>3.0.10.Final</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5</version>
        <type>jar</type>
    </dependency>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-web-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency> 

-1

Apache httpClient 4.5.x 를 사용하는 경우 다음을 시도하십시오.

public static void main(String... args)  {

    try (CloseableHttpClient httpclient = createAcceptSelfSignedCertificateClient()) {
        HttpGet httpget = new HttpGet("https://example.com");
        System.out.println("Executing request " + httpget.getRequestLine());

        httpclient.execute(httpget);
        System.out.println("----------------------------------------");
    } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException | IOException e) {
        throw new RuntimeException(e);
    }
}

private static CloseableHttpClient createAcceptSelfSignedCertificateClient()
        throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {

    // use the TrustSelfSignedStrategy to allow Self Signed Certificates
    SSLContext sslContext = SSLContextBuilder
            .create()
            .loadTrustMaterial(new TrustSelfSignedStrategy())
            .build();

    // we can optionally disable hostname verification. 
    // if you don't want to further weaken the security, you don't have to include this.
    HostnameVerifier allowAllHosts = new NoopHostnameVerifier();

    // create an SSL Socket Factory to use the SSLContext with the trust self signed certificate strategy
    // and allow all hosts verifier.
    SSLConnectionSocketFactory connectionFactory = new SSLConnectionSocketFactory(sslContext, allowAllHosts);

    // finally create the HttpClient using HttpClient factory methods and assign the ssl socket factory
    return HttpClients
            .custom()
            .setSSLSocketFactory(connectionFactory)
            .build();
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.