108

Apache HttpClient 4.3の SSL 証明書を無視する (すべてを信頼する) にはどうすればよいですか?

SOで見つけたすべての回答は以前のバージョンを扱い、APIが変更されました。

関連している:

編集:

  • これはテストのみを目的としています。子供たち、自宅で(または本番環境で)試してはいけません
4

16 に答える 16

152

以下のコードは、自己署名証明書を信頼するために機能します。クライアントを作成するときは、 TrustSelfSignedStrategyを使用する必要があります。

SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
        builder.build());
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(
        sslsf).build();

HttpGet httpGet = new HttpGet("https://some-server");
CloseableHttpResponse response = httpclient.execute(httpGet);
try {
    System.out.println(response.getStatusLine());
    HttpEntity entity = response.getEntity();
    EntityUtils.consume(entity);
} finally {
    response.close();
}

意図的には含めませんでしたSSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER。要点は、自己署名証明書でテストできるようにすることでした。そのため、認証局から適切な証明書を取得する必要はありません。正しいホスト名を使用して自己署名証明書を簡単に作成できるため、SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIERフラグを追加する代わりにそれを行います。

于 2013-10-22T12:50:45.780 に答える
95

上記の PoolingHttpClientConnectionManager プロシージャを使用している場合、カスタム SSLContext は無視されます。PoolingHttpClientConnectionManager を作成するときに、コンストラクターで socketFactoryRegistry を渡す必要があります。

SSLContextBuilder builder = SSLContexts.custom();
builder.loadTrustMaterial(null, new TrustStrategy() {
    @Override
    public boolean isTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        return true;
    }
});
SSLContext sslContext = builder.build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
        sslContext, new X509HostnameVerifier() {
            @Override
            public void verify(String host, SSLSocket ssl)
                    throws IOException {
            }

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

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

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

Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
        .<ConnectionSocketFactory> create().register("https", sslsf)
        .build();

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(
        socketFactoryRegistry);
CloseableHttpClient httpclient = HttpClients.custom()
        .setConnectionManager(cm).build();
于 2013-11-13T10:11:11.760 に答える
24

vasektによる回答への小さな追加:

PoolingHttpClientConnectionManager を使用すると、SocketFactoryRegistry で提供されるソリューションが機能します。

ただし、プレーンな http 経由の接続は機能しなくなりました。それらを再び機能させるには、さらに http プロトコル用の PlainConnectionSocketFactory を追加する必要があります。

Registry<ConnectionSocketFactory> socketFactoryRegistry = 
  RegistryBuilder.<ConnectionSocketFactory> create()
  .register("https", sslsf)
  .register("http", new PlainConnectionSocketFactory()).build();
于 2013-12-10T10:12:04.187 に答える
17

さまざまなオプションを試した後、次の構成は http と https の両方で機能しました。

SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                builder.build(), SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

Registry<ConnectionSocketFactory> registry = RegistryBuilder. 
                 <ConnectionSocketFactory> create()
                .register("http", new PlainConnectionSocketFactory())
                .register("https", sslsf)
                .build();

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
cm.setMaxTotal(2000);

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

http-client 4.3.3 を使用しています:compile 'org.apache.httpcomponents:httpclient:4.3.3'

于 2014-08-07T16:06:50.207 に答える
9

よりシンプルで短い作業コード:

私たちはHTTPClient 4.3.5を使用しており、スタックオーバーフローに存在するほとんどすべてのソリューションを試してみましたが、何もありませんでした。問題を考えて理解した後、完全に機能する次のコードにたどり着きました。

投稿リクエストを行うために使用するいくつかの方法...

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

通常の形式で HttpPost インスタンスを呼び出して使用し続ける

于 2015-04-03T15:36:02.573 に答える
7

これは、「curl --insecure」に相当する、上記の手法の実用的な要約です。

HttpClient getInsecureHttpClient() throws GeneralSecurityException {
    TrustStrategy trustStrategy = new TrustStrategy() {
        @Override
        public boolean isTrusted(X509Certificate[] chain, String authType) {
            return true;
        }
    };

    HostnameVerifier hostnameVerifier = new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };

    return HttpClients.custom()
            .setSSLSocketFactory(new SSLConnectionSocketFactory(
                    new SSLContextBuilder().loadTrustMaterial(trustStrategy).build(),
                    hostnameVerifier))
            .build();
}
于 2016-12-05T20:02:19.157 に答える
6

http クライアント 4.5 を使用する場合、javasx.net.ssl.HostnameVerifier を使用して任意のホスト名を許可する必要がありました (テスト目的で)。これが私がやったことです:

CloseableHttpClient httpClient = null;
    try {
        SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
        sslContextBuilder.loadTrustMaterial(null, new TrustSelfSignedStrategy());

        HostnameVerifier hostnameVerifierAllowAll = new HostnameVerifier() 
            {
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            };

        SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContextBuilder.build(), hostnameVerifierAllowAll);

        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(
            new AuthScope("192.168.30.34", 8443),
            new UsernamePasswordCredentials("root", "password"));

        httpClient = HttpClients.custom()
            .setSSLSocketFactory(sslSocketFactory)
            .setDefaultCredentialsProvider(credsProvider)
            .build();

        HttpGet httpGet = new HttpGet("https://192.168.30.34:8443/axis/services/getStuff?firstResult=0&maxResults=1000");

        CloseableHttpResponse response = httpClient.execute(httpGet);

        int httpStatus = response.getStatusLine().getStatusCode();
        if (httpStatus >= 200 && httpStatus < 300) { [...]
        } else {
            throw new ClientProtocolException("Unexpected response status: " + httpStatus);
        }

    } catch (Exception ex) {
        ex.printStackTrace();
    }
    finally {
        try {
            httpClient.close();
        } catch (IOException ex) {
            logger.error("Error while closing the HTTP client: ", ex);
        }
    }
于 2016-01-25T11:41:15.473 に答える
3

それPoolingHttpClientConnectionManagerに加えて、コードRegistry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create().register("https", sslFactory).build(); を使用して非同期httpclientが必要な場合は、次のようにする必要がありますPoolingNHttpClientConnectionManager

SSLContextBuilder builder = SSLContexts.custom();
builder.loadTrustMaterial(null, new TrustStrategy() {
    @Override
    public boolean isTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        return true;
    }
});
SSLContext sslContext = builder.build();
SchemeIOSessionStrategy sslioSessionStrategy = new SSLIOSessionStrategy(sslContext, 
                new HostnameVerifier(){
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;// TODO as of now allow all hostnames
            }
        });
Registry<SchemeIOSessionStrategy> sslioSessionRegistry = RegistryBuilder.<SchemeIOSessionStrategy>create().register("https", sslioSessionStrategy).build();
PoolingNHttpClientConnectionManager ncm  = new PoolingNHttpClientConnectionManager(new DefaultConnectingIOReactor(),sslioSessionRegistry);
CloseableHttpAsyncClient asyncHttpClient = HttpAsyncClients.custom().setConnectionManager(ncm).build();
asyncHttpClient.start();        
于 2016-02-19T09:19:18.363 に答える