Bỏ qua chứng chỉ SSL trong Apache HttpClient 4.3


102

Làm cách nào để bỏ qua chứng chỉ SSL (tin cậy tất cả) cho Apache HttpClient 4.3 ?

Tất cả các câu trả lời mà tôi tìm thấy trên SO đều xử lý các phiên bản trước đó và API đã thay đổi.

Có liên quan:

Biên tập:

  • Nó chỉ dành cho mục đích thử nghiệm. Trẻ em, không thử nó ở nhà (hoặc sản xuất)

Câu trả lời:


146

Mã dưới đây hoạt động để tin cậy các chứng chỉ tự ký. Bạn phải sử dụng TrustSelfSignedStrategy khi tạo ứng dụng khách của mình:

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

Tôi không cố ý đưa SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIERvào mục đích: Mục đích là cho phép thử nghiệm với các chứng chỉ tự ký, do đó bạn không cần phải lấy chứng chỉ thích hợp từ tổ chức chứng nhận. Bạn có thể dễ dàng tạo chứng chỉ tự ký với tên máy chủ chính xác, vì vậy hãy làm điều đó thay vì thêm SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIERcờ.


8
Tôi đã phải thêm đối số SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER vào phương thức khởi tạo để điều này hoạt động với HttpClientBuilder (như đã đề cập trong phản hồi của holmis83 với jarkt).
dejuknow

cũng tham khảo ví dụ trên httpclient site hc.apache.org/httpcomponents-client-4.3.x/httpclient/examples/…
arajashe

2
Tôi cũng phải sử dụng ALLOW_ALL_HOSTNAME_VERIFIER: SSLConnectionSocketFactory (builder.build (), SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Tên hiển thị

Mã này hoạt động với tôi mà không sử dụng hàm tạo không được dùng nữa với đối sốSSLConnectionSocketFactory.ALLOW_‌​ALL_HOSTNAME_VERIFIER
user11153

Tôi ước bạn đã chỉ định tham chiếu đầy đủ về lớp bạn đang sử dụng. SSLContextBuilderIdea tìm thấy nhiều lớp được gọi .
MasterMind

91

Nếu bạn đang sử dụng thủ tục PoolingHttpClientConnectionManager ở trên không hoạt động, thì SSLContext tùy chỉnh sẽ bị bỏ qua. Bạn phải chuyển socketFactoryRegistry trong contructor khi tạo PoolingHttpClientConnectionManager.

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

11
Thay vì tạo X509HostnameVerifier của riêng bạn, bạn có thể sử dụng SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER.
holmis83 13/12/13

Như được đánh dấu bên dưới bởi @ rich95, mặc định cho HttpClients là cung cấp cho bạn một PoolingHttpClient, vì vậy điều này rất thường xuyên có liên quan. Tôi đã phải thử khá nhiều câu trả lời trước khi nhận thấy mình cần điều này.
SunSear

1
Đã thử áp dụng điều này trên WebSphere và nhận được "java.security.KeyStoreException: IBMTrustManager: Sự cố khi truy cập cửa hàng tin cậy java.io.IOException: Định dạng kho khóa không hợp lệ" Để tránh, bạn cần vượt qua KeyStore trustStore = KeyStore.getInstance (KeyStore.getDefaultType ()); thay vì null để builder.loadTrustMaterial
Georgy Gobozov

1
Trên thực tế, với HttpClient 4.5, cả hai HttpClients.custom().setConnectionManager(cm).build()HttpClients.custom().setSSLSocketFactory(connectionFactory).build()sẽ làm việc, do đó bạn không cần phải tạo ra mộtPoolingHttpClientConnectionManager
soulmachine

Làm thế nào để sử dụng PoolingHttpClientConnectionManager sau khi tạo này, mã của tôi đang làm việc nhưng tôi muốn biết làm các công trình kết nối tổng hợp hay không
Labeo

34

Như một phần bổ sung cho câu trả lời của @mavroprovato, nếu bạn muốn tin tưởng tất cả các chứng chỉ thay vì chỉ tự ký, bạn sẽ thực hiện (theo kiểu mã của bạn)

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

hoặc (sao chép-dán trực tiếp từ mã của riêng tôi):

import javax.net.ssl.SSLContext;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.ssl.SSLContexts;

// ...

        SSLContext sslContext = SSLContexts
                .custom()
                //FIXME to contain real trust store
                .loadTrustMaterial(new TrustStrategy() {
                    @Override
                    public boolean isTrusted(X509Certificate[] chain,
                        String authType) throws CertificateException {
                        return true;
                    }
                })
                .build();

Và nếu bạn cũng muốn bỏ qua xác minh tên máy chủ, bạn cần phải đặt

    CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(
            sslsf).setSSLHostnameVerifier( NoopHostnameVerifier.INSTANCE).build();

cũng. (ALLOW_ALL_HOSTNAME_VERIFIER không được dùng nữa).

Cảnh báo bắt buộc: bạn thực sự không nên làm điều này, chấp nhận tất cả các chứng chỉ là một điều tồi tệ. Tuy nhiên, có một số trường hợp sử dụng hiếm hoi mà bạn muốn làm điều này.

Như một lưu ý cho mã đã đưa ra trước đó, bạn sẽ muốn đóng phản hồi ngay cả khi httpclient.execute () ném một ngoại lệ

CloseableHttpResponse response = null;
try {
    response = httpclient.execute(httpGet);
    System.out.println(response.getStatusLine());
    HttpEntity entity = response.getEntity();
    EntityUtils.consume(entity);
}
finally {
    if (response != null) {
        response.close();
    }
}

Mã trên đã được thử nghiệm bằng

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.3</version>
</dependency>

Và đối với những người quan tâm, đây là bộ thử nghiệm đầy đủ của tôi:

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.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.junit.Test;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLPeerUnverifiedException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class TrustAllCertificatesTest {
    final String expiredCertSite = "https://expired.badssl.com/";
    final String selfSignedCertSite = "https://self-signed.badssl.com/";
    final String wrongHostCertSite = "https://wrong.host.badssl.com/";

    static final TrustStrategy trustSelfSignedStrategy = new TrustSelfSignedStrategy();
    static final TrustStrategy trustAllStrategy = new TrustStrategy(){
        public boolean isTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            return true;
        }
    };

    @Test
    public void testSelfSignedOnSelfSignedUsingCode() throws Exception {
        doGet(selfSignedCertSite, trustSelfSignedStrategy);
    }
    @Test(expected = SSLHandshakeException.class)
    public void testExpiredOnSelfSignedUsingCode() throws Exception {
        doGet(expiredCertSite, trustSelfSignedStrategy);
    }
    @Test(expected = SSLPeerUnverifiedException.class)
    public void testWrongHostOnSelfSignedUsingCode() throws Exception {
        doGet(wrongHostCertSite, trustSelfSignedStrategy);
    }

    @Test
    public void testSelfSignedOnTrustAllUsingCode() throws Exception {
        doGet(selfSignedCertSite, trustAllStrategy);
    }
    @Test
    public void testExpiredOnTrustAllUsingCode() throws Exception {
        doGet(expiredCertSite, trustAllStrategy);
    }
    @Test(expected = SSLPeerUnverifiedException.class)
    public void testWrongHostOnTrustAllUsingCode() throws Exception {
        doGet(wrongHostCertSite, trustAllStrategy);
    }

    @Test
    public void testSelfSignedOnAllowAllUsingCode() throws Exception {
        doGet(selfSignedCertSite, trustAllStrategy, NoopHostnameVerifier.INSTANCE);
    }
    @Test
    public void testExpiredOnAllowAllUsingCode() throws Exception {
        doGet(expiredCertSite, trustAllStrategy, NoopHostnameVerifier.INSTANCE);
    }
    @Test
    public void testWrongHostOnAllowAllUsingCode() throws Exception {
        doGet(expiredCertSite, trustAllStrategy, NoopHostnameVerifier.INSTANCE);
    }

    public void doGet(String url, TrustStrategy trustStrategy, HostnameVerifier hostnameVerifier) throws Exception {
        SSLContextBuilder builder = new SSLContextBuilder();
        builder.loadTrustMaterial(trustStrategy);
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                builder.build());
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(
                sslsf).setSSLHostnameVerifier(hostnameVerifier).build();

        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response = httpclient.execute(httpGet);
        try {
            System.out.println(response.getStatusLine());
            HttpEntity entity = response.getEntity();
            EntityUtils.consume(entity);
        } finally {
            response.close();
        }
    }
    public void doGet(String url, TrustStrategy trustStrategy) throws Exception {

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

        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response = httpclient.execute(httpGet);
        try {
            System.out.println(response.getStatusLine());
            HttpEntity entity = response.getEntity();
            EntityUtils.consume(entity);
        } finally {
            response.close();
        }
    }
}

(dự án thử nghiệm làm việc trong github )


1
HttpClient # thực thi sẽ không bao giờ trả về đối tượng phản hồi null trong trường hợp có ngoại lệ. Hơn nữa, việc triển khai HttpClient sẽ đảm bảo tự động phân bổ tất cả các tài nguyên hệ thống như các kết nối đã thuê trong trường hợp có ngoại lệ trong quá trình thực hiện yêu cầu. Xử lý ngoại lệ được sử dụng bởi mavroprovato là hoàn toàn phù hợp.
ok2c

@oleg quan điểm của Closable interface là "Đóng [...] luồng và giải phóng bất kỳ tài nguyên hệ thống nào được liên kết với nó. Nếu luồng đã bị đóng thì việc gọi phương thức này không có hiệu lực." vì vậy cách tốt nhất là sử dụng nó ngay cả khi không cần thiết. Ngoài ra, tôi không hiểu nhận xét trả về phản hồi null - tất nhiên là không, nếu nó ném một ngoại lệ, nó không trả lại bất cứ điều gì?
eis

1
Apache HttpClient không bao giờ trả về đối tượng phản hồi null hoặc khởi tạo một phần. Này không có gì để làm với bao nhiêu lần # Đóng được gọi, nhưng kiểm tra null thay vì hoàn toàn không cần thiết vào khối finally
ok2c

@oleg và không bao giờ mã mà tôi đã đưa ra giả sử nó sẽ trả về một đối tượng phản hồi null hoặc được khởi tạo một phần, hoặc thậm chí kiểm tra trường hợp như vậy. Tôi không biết bạn đang nói gì?
eis

1
[ Thở dài ] mà hoàn toàn không cần thiết cho rằng HttpResponse có thể không bao giờ được null và trong trường hợp của một ngoại lệ phương pháp #execute sẽ chấm dứt mà không trả lại một phản ứng ;-)
ok2c

22

Một bổ sung nhỏ cho câu trả lời của jarkt:

Giải pháp được cung cấp với SocketFactoryRegistry hoạt động khi sử dụng PoolingHttpClientConnectionManager.

Tuy nhiên, các kết nối thông qua http thuần túy không còn hoạt động nữa. Bạn phải thêm PlainConnectionSocketFactory cho giao thức http để làm cho chúng hoạt động trở lại:

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

Tôi tin rằng httpgiao thức đang sử dụng PlainConnectionSocketFactory theo mặc định. Tôi chỉ đăng ký httpshttpclientvẫn có thể nhận được các URL HTTP đơn giản. vì vậy tôi không nghĩ rằng bước này là cần thiết.
soulmachine

@soulmachine nó sẽ không choPoolingHttpClientConnectionManager
amseager

15

Sau khi thử các tùy chọn khác nhau, cấu hình sau hoạt động cho cả http và 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);//max connection


        //System.setProperty("jsse.enableSNIExtension", "false"); //""
        CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .setConnectionManager(cm)
                .build();

Tôi đang sử dụng http-client 4.3.3 -

compile 'org.apache.httpcomponents:httpclient:4.3.3'


1
Cảm ơn bạn đã cung cấp một ví dụ hoạt động toàn diện, đầy đủ! Tôi đã gặp phải nhiều vấn đề với các giải pháp trước đó và điều này đã giúp ích rất nhiều. Cũng đã giúp bạn cung cấp các câu lệnh nhập, vì có nhiều lớp trùng tên, làm tăng thêm sự nhầm lẫn.
helmy 20/09/17

8

Mã làm việc đơn giản hơn và ngắn hơn:

Chúng tôi đang sử dụng HTTPClient 4.3.5 và chúng tôi đã thử hầu hết các giải pháp tồn tại trên stackoverflow nhưng không có gì, Sau khi suy nghĩ và tìm ra vấn đề, chúng tôi đi đến đoạn mã sau hoạt động hoàn hảo, chỉ cần thêm nó trước khi tạo phiên bản HttpClient.

một số phương pháp mà bạn sử dụng để thực hiện yêu cầu đăng bài ...

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

tiếp tục gọi và sử dụng phiên bản HttpPost ở dạng bình thường


Làm cách nào chúng ta có thể đăng Dữ liệu trong tiêu đề? Nếu chúng tôi đã làm như vậy, thì hãy xem HTTP / 1.1 400 Yêu cầu không hợp lệ

6

Đây là sự chắt lọc hoạt động của các kỹ thuật trên, tương đương với "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();
}

5

Khi sử dụng máy khách http 4.5, tôi phải sử dụng javasx.net.ssl.HostnameVerifier để cho phép bất kỳ tên máy chủ nào (cho mục đích thử nghiệm). Đây là những gì tôi đã kết thúc:

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

Việc triển khai HostnameVerifier đã giải quyết được vấn đề cho HTTPClient 4.5.
digz6666

cho những ai yêu thích lambdas (JDK1.8), có thể thay thế SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContextBuilder.build(), hostnameVerifierAllowAll);bằng SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContextBuilder.build(), (hostName, sslSession) -> true);. Nó tránh lớp ẩn danh và làm cho mã dễ đọc hơn một chút.
Vielinko

3

Ngày đầu PoolingHttpClientConnectionManagercùng với Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create().register("https", sslFactory).build(); Nếu bạn muốn một không đồng bộ httpclient sử dụng PoolingNHttpClientConnectionManagermã shoudl thể tương tự như sau

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

3

Nếu bạn đang sử dụng HttpClient 4.5.x, mã của bạn có thể tương tự như sau:

SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null,
        TrustSelfSignedStrategy.INSTANCE).build();
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
        sslContext, NoopHostnameVerifier.INSTANCE);

HttpClient httpClient = HttpClients.custom()
                                   .setDefaultCookieStore(new BasicCookieStore())
                                   .setSSLSocketFactory(sslSocketFactory)
                                   .build();

Không làm việc cho tôi. Tôi đang sử dụng HttpClient: 4.5.5. và HttpCore 4.4.9
Vijay Kumar

2
class ApacheHttpClient {

    /***
     * This is a https get request that bypasses certificate checking and hostname verifier.
     * It uses basis authentication method.
     * It is tested with Apache httpclient-4.4.
     * It dumps the contents of a https page on the console output.
     * It is very similar to http get request, but with the additional customization of
     *   - credential provider, and
     *   - SSLConnectionSocketFactory to bypass certification checking and hostname verifier.
     * @param path String
     * @param username String
     * @param password String
     * @throws IOException
     */
    public void get(String path, String username, String password) throws IOException {
        final CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultCredentialsProvider(createCredsProvider(username, password))
                .setSSLSocketFactory(createGenerousSSLSocketFactory())
                .build();

        final CloseableHttpResponse response = httpClient.execute(new HttpGet(path));
        try {
            HttpEntity entity = response.getEntity();
            if (entity == null)
                return;
            System.out.println(EntityUtils.toString(entity));
        } finally {
            response.close();
            httpClient.close();
        }
    }

    private CredentialsProvider createCredsProvider(String username, String password) {
        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(
                AuthScope.ANY,
                new UsernamePasswordCredentials(username, password));
        return credsProvider;
    }

    /***
     * 
     * @return SSLConnectionSocketFactory that bypass certificate check and bypass HostnameVerifier
     */
    private SSLConnectionSocketFactory createGenerousSSLSocketFactory() {
        SSLContext sslContext;
        try {
            sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, new TrustManager[]{createGenerousTrustManager()}, new SecureRandom());
        } catch (KeyManagementException | NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
        return new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
    }

    private X509TrustManager createGenerousTrustManager() {
        return new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] cert, String s) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] cert, String s) throws CertificateException {
            }

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

2

Tin tưởng tất cả chứng chỉ trong Apache HTTP Client

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, new java.security.SecureRandom());
                SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                        sc);
                httpclient = HttpClients.custom().setSSLSocketFactory(
                        sslsf).build();
                HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

Điều này hoạt động tốt với httpclient 4.5.9, Chỉ cần sao chép và dán toàn bộ nội dung là xong.
sathya

1

(Tôi sẽ thêm một nhận xét trực tiếp vào câu trả lời của jarkt nhưng tôi không có đủ điểm danh tiếng (không chắc về logic ở đó)

Dù sao đi nữa ... điều tôi muốn nói là ngay cả khi bạn không tạo / yêu cầu PoolingConnection một cách rõ ràng, không có nghĩa là bạn không nhận được.

Tôi đã phát điên khi cố gắng tìm ra lý do tại sao giải pháp ban đầu không hiệu quả với tôi, nhưng tôi đã bỏ qua câu trả lời của jarkt vì nó "không áp dụng cho trường hợp của tôi" - sai!

Tôi đang nhìn chằm chằm vào dấu vết ngăn xếp của mình khi thấp và tôi thấy một PoolingConnection ở giữa nó. Bang - Tôi mệt mỏi với sự bổ sung và thành công của anh ấy !! (bản demo của chúng tôi là vào ngày mai và tôi đã trở nên tuyệt vọng) :-)


0

Bạn có thể sử dụng đoạn mã sau để tải phiên bản HttpClient mà không cần kiểm tra chứng nhận ssl.

private HttpClient getSSLHttpClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {

        LogLoader.serverLog.trace("In getSSLHttpClient()");

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

        TrustManager tm = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

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

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

        context.init(null, new TrustManager[] { tm }, null);

        HttpClientBuilder builder = HttpClientBuilder.create();
        SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(context);
        builder.setSSLSocketFactory(sslConnectionFactory);

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

        PoolingHttpClientConnectionManager ccm = new PoolingHttpClientConnectionManager(registry);
        ccm.setMaxTotal(BaseConstant.CONNECTION_POOL_SIZE);
        ccm.setDefaultMaxPerRoute(BaseConstant.CONNECTION_POOL_SIZE);
        builder.setConnectionManager((HttpClientConnectionManager) ccm);

        builder.disableRedirectHandling();

        LogLoader.serverLog.trace("Out getSSLHttpClient()");

        return builder.build();
    }

0

Chỉnh sửa nhẹ để trả lời từ @divbyzero ở trên để khắc phục các cảnh báo bảo mật sonar

CloseableHttpClient getInsecureHttpClient() throws GeneralSecurityException {
            TrustStrategy trustStrategy = (chain, authType) -> true;

            HostnameVerifier hostnameVerifier = (hostname, session) -> hostname.equalsIgnoreCase(session.getPeerHost());

            return HttpClients.custom()
                    .setSSLSocketFactory(new SSLConnectionSocketFactory(new SSLContextBuilder().loadTrustMaterial(trustStrategy).build(), hostnameVerifier))
                    .build();
        }

0

Ban đầu, tôi có thể vô hiệu hóa cho localhost bằng chiến lược tin cậy, sau đó tôi đã thêm NoopHostnameVerifier. Bây giờ nó sẽ hoạt động cho cả localhost và bất kỳ tên máy nào

SSLContext sslContext = SSLContextBuilder.create().loadTrustMaterial(null, new TrustStrategy() {

            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                return true;
            }

        }).build();
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslContext, NoopHostnameVerifier.INSTANCE);
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.