Cách bỏ qua lỗi chứng chỉ SSL trong Apache HttpClient 4.0


125

Làm cách nào để vượt qua các lỗi chứng chỉ SSL không hợp lệ với Apache HttpClient 4.0?


12
Cần lưu ý rằng các câu trả lời cho câu hỏi này không làm nhiều hơn những gì được hỏi: họ cho phép bạn bỏ qua lỗi nhưng không khắc phục vấn đề tiềm ẩn (giống như tháo pin khỏi thiết bị báo khói thay vì dập lửa ). Chứng chỉ có mục đích đảm bảo tính bảo mật của kết nối SSL / TLS, bỏ qua những lỗi đó dẫn đến lỗ hổng cho cuộc tấn công MITM. Sử dụng chứng chỉ kiểm tra thay vì bỏ qua lỗi.
Bruno


46
"Giống như tháo pin khỏi thiết bị báo khói" Bạn có thể mang đến cho các nhà phát triển khác lợi ích của sự nghi ngờ và cho rằng họ biết họ đang làm gì. Có lẽ động lực cho câu hỏi này là thử nghiệm cục bộ và OP mong muốn chạy thử nghiệm nhanh mà không phải trải qua số lượng khủng khiếp của bản tóm tắt Java cần thiết để thiết lập ngay cả một môi trường SSL đơn giản. Có lẽ ai đó chỉ có thể trả lời câu hỏi mà không cần đi vào một bài giảng "thánh hơn cả bạn".
Mike

Tức là trong máy chủ JIRA nội bộ của công ty chúng tôi có một số "chứng chỉ dựa trên chính sách bảo mật windows" hợp lệ trên các máy Windows có trong miền và không hợp lệ trên máy khác. Tôi không thể kiểm soát chính sách này và vẫn muốn gọi API JIRA REST.
odiszapc

1
@Bruno Việc không thể vô hiệu hóa thiết bị phát hiện khói trong khoảng thời gian 30-60 phút trong khi xử lý đám cháy nhà bếp nhỏ cho thấy sự thiếu hiểu biết điên rồ về mô hình sử dụng của một số quan chức pháp lý tại một số điểm mà tôi cảm thấy giáp với tội phạm. Việc có một khái niệm "tháo pin ra khỏi thiết bị báo khói" đã chứng minh điều này. Tôi cảm thấy về cùng một mức độ tức giận về việc phải có chứng chỉ để làm việc cho một bài kiểm tra đơn giản mà tôi biết không có sự phân nhánh bảo mật. Sự tồn tại của câu hỏi này đã chứng minh điều này.
Bill K

Câu trả lời:


84

Bạn cần tạo SSLContext bằng TrustManager của riêng bạn và tạo lược đồ HTTPS bằng bối cảnh này. Đây là mã

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
Nói rằng tôi không muốn mua chứng chỉ SSL hợp lệ cho trang web của mình và chỉ muốn sử dụng nó, đoạn mã này có thể giúp gì? Tại sao tôi không thấy bất kỳ phần nào cần URL hoặc xử lý ngoại lệ là cần thiết?
Việt

19
Hmm, nó nói với tôi rằng 'SSLSocketFactory (ssslCont)' mới đang mong đợi KeyStore chứ không phải SSLContext. Tui bỏ lỡ điều gì vậy?
MSpeed

2
Tôi nhận được lỗi rằng X509TrustManager không thể chuyển sang TrustManager.
MW.

2
Đảm bảo rằng bạn nhập các gói chính xác, tức là từ org.apache.http.
cai ngục

2
Bất cứ ai biết làm thế nào để ném tất cả điều này với nhau bằng cách sử dụng HttpClientBuilder?
Ali

112

Tất cả các câu trả lời khác đều không được chấp nhận hoặc không hoạt động đối với HttpClient 4.3.

Đây là một cách để cho phép tất cả tên máy chủ khi xây dựng ứng dụng khách http.

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

Hoặc nếu bạn đang sử dụng phiên bản 4.4 trở lên, cuộc gọi được cập nhật sẽ như thế này:

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

Cảm ơn câu trả lời, tôi muốn biết HttpsCl Client từ gói nào tôi đang sử dụng trong trình biên dịch Android ("org.apache.httpcomponents: httpclient: 4.3.4") nhưng lớp này không xuất hiện.
Juan Saravia

1
Gói của nó là org.apache.http.impl.client.HttpClrons.
erversteeg

14
Điều này hoạt động xung quanh một tên máy chủ không khớp (tôi giả sử), nhưng nó dường như không hoạt động khi chứng chỉ không được ký bởi một cơ quan đáng tin cậy.
twm

1
@twm đó là lý do tại sao nó nói "cho phép tất cả tên máy chủ", các vấn đề về niềm tin đòi hỏi cấu hình khác nhau.
eis

1
@eis, tôi đã chỉ ra rằng câu trả lời này giải quyết câu hỏi ban đầu trong một số trường hợp nhất định nhưng không phải là câu hỏi khác.
twm

43

Chỉ cần thực hiện điều này với HTTPClient 4.5 mới hơn và có vẻ như họ đã từ chối một số thứ kể từ 4.4, vì vậy đây là đoạn trích phù hợp với tôi và sử dụng API gần đây nhất:

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

Làm việc cho tôi cũng cho httpclient 4.5.2
Vikas Ranjan

cái này được cập nhật cho HttpClient 4.5
Bạn thật tuyệt vời vào

31

Chỉ cần cho bản ghi, có một cách đơn giản hơn nhiều để thực hiện tương tự với 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
Bạn đang thiếu một số mã trong mẫu này? Có lẽ một cuộc gọi đến httpClient.set ...?
Xám

6
httpclient.getConnectionManager (). getSchemeRegistry (). đăng ký (Lược đồ mới ("https", 443, sslsf));
Ben Flynn

8
SSLSocketFactory không được chấp nhận trong HttpClient 4.3
Toilal

1
Nếu sử dụng Java 8, bạn thậm chí có thểnew SSLSocketFactory((chain, authType) -> true);
jlb

28

Apache httpClient 4.5.5

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

Không có API không dùng nữa đã được sử dụng.

Trường hợp kiểm tra xác minh đơn giản:

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

Cảm ơn bạn! Chỉ cần thay đổi TrustAllStrategy.INSTANCEvới TrustSelfSignedStrategy.INSTANCEtrong câu trả lời này.
Percy Vega

Điều này đã không làm việc cho tôi. javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: xây dựng đường dẫn PKIX không thành công: sun.security.
Carrier.certpath.SunCertPathBuilderException

26

Đối với bản ghi, đã thử nghiệm với httpclient 4.3.6 và tương thích với Executor của api thông thạo:

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
Đối với HttpClient 4.4 trở lên, bạn phải thực hiện việc này - và cũng có thể cần phải tạo một SSLConnectionSocketFactorycách sử dụng đó SSLContextvà xác định điều này trong một Registry<ConnectionSocketFactory>, nếu bạn sẽ tạo một PoolingHttpClientConnectionManager. Các câu trả lời khác phổ biến hơn, nhưng không hoạt động tại HttpClient 4.4.
Thomas W

1
Hoạt động chính xác như thế này với httpclient-4.3.5.jar.
Harald

18

Đối với 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();

Điều này được trích từ thực hiện làm việc thực tế của chúng tôi.

Các câu trả lời khác là phổ biến, nhưng đối với HttpClient 4.4, chúng không hoạt động. Tôi đã dành hàng giờ để thử và hết khả năng, nhưng dường như đã có sự thay đổi & di chuyển API cực kỳ lớn ở 4.4.

Xem thêm một lời giải thích đầy đủ hơn một chút tại: http://literatejava.com/networks/ignore-ssl-certert-errors-apache-httpclient-4-4/

Mong rằng sẽ giúp!


2
Tôi là bit SSLContext mà tôi cần. Quá nhiều nghĩa vụ.
muttonUp 13/03/2015

14

Nếu tất cả những gì bạn muốn làm là loại bỏ các lỗi tên máy chủ không hợp lệ, bạn chỉ có thể làm:

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

8
Phương thức sf.sethostnameVerifier đã không được chấp nhận kể từ ngày 4.1. Thay thế là sử dụng một trong các nhà xây dựng. Ví dụ:SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
kaliatech

Điều này rất hữu ích khi tôi phải xử lý mã kế thừa.
DuncanSungWKim

9

Chúng tôi đang sử dụng HTTPClient 4.3.5 và chúng tôi đã thử hầu hết tất cả 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 đế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 để gọi khi thực hiện yêu cầu 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 yêu cầu của bạn ở dạng bình thường


7

Với thông thạo 4.5.2 tôi đã phải thực hiện sửa đổi sau đây để làm cho nó hoạt động.

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
Đây là giải pháp duy nhất làm việc cho tôi. Tôi đã thử các giải pháp trên cho 4.3 và 4.4 trước khi nâng cấp lên 4.5 và thử cách này.
dirkoneill

6

Đây là cách tôi đã làm nó -

  1. Tạo MockSSLSocketFactory của riêng tôi (Lớp đính kèm bên dưới)
  2. Sử dụng nó để khởi tạo DefaultHttpClient. Cài đặt proxy cần được cung cấp nếu sử dụng proxy.

Khởi tạo 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);

Nhà máy Mock 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;
    }
};
}

Nếu đằng sau một proxy, cần phải làm điều này -

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

Nó sẽ giúp nếu bạn bao gồm hàng nhập khẩu trong tương lai. Có hai lớp khác nhau.
AndroidDev

4

Trong phần mở rộng cho câu trả lời của ZZ Coder, sẽ rất hay khi ghi đè lên bộ lưu trữ tên máy chủ.

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

Bạn có thể đạt được điều tương tự chỉ bằng cách thực hiệnsf.setHostnameVerifier(new AllowAllHostnameVerifier());
Dan Dyer

7
Sf.sethostnameVerifier đã không được chấp nhận kể từ ngày 4.1. Thay thế là sử dụng một trong các nhà xây dựng. Ví dụ: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

Để chấp nhận tất cả các chứng chỉ trong HttpClient 4.4.x, bạn có thể sử dụng một lớp lót sau đây khi tạo httpClient:

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

Tôi nhận được điều này: Nguyên nhân bởi: javax.net.ssl.SSLHandshakeException: java.security.cert.Cert veException: Không có tên thay thế chủ đề?

Làm cách nào để cho phép kết nối với các trang web SSL mà không cần certs trong API HTTPClient hoặc API RestClient?

4

Đã thử nghiệm với HTTPClient 4.5.5 với API thông thạo

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

Mã dưới đây hoạt động với 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()));
    }
}

Đầu ra từ mã là

Mã

Đầu ra trên trình duyệt là

SSL xấu

Các pom được sử dụng là dưới đây

<?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>

cảm ơn câu trả lời cập nhật, tôi đã trao tiền thưởng cho anh chàng mới được "chào đón" nhưng tôi chỉ muốn câu trả lời cập nhật cho mọi người!

1
@feelingunwelcome, chắc chắn rồi. Tôi cũng đã nâng đỡ anh ấy :-)
Tarun Lalwani

2

một phiên bản hoạt động đầy đủ cho Apache HttpClient 4.1.3 (dựa trên mã của oleg ở trên, nhưng nó vẫn cần một allow_all_hostname_verifier trên hệ thống của tôi):

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

Lưu ý Tôi đang ném lại tất cả các ngoại lệ vì thực sự, tôi không thể làm gì nhiều nếu bất kỳ điều này không thành công trong một hệ thống thực!


2

Nếu bạn đang sử dụng API thông thạo , bạn cần thiết lập nó thông qua Executor:

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

... sslContextSSLContext được tạo ở đâu như trong câu trả lời của ZZ Coder .

Sau đó, bạn có thể thực hiện các yêu cầu http của mình dưới dạng:

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

Lưu ý: đã thử nghiệm với HTTPClient 4.2


Thật không may không dùng nữa trong 4.3: "Không dùng nữa. (4.3) không sử dụng."
STM

2

Đã thử nghiệm với 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;
}

}


Làm cách nào để đặt giá trị trong Tiêu đề nếu tôi muốn làm điều đó?

2

Đã thử nghiệm trên 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

Nếu bạn gặp phải vấn đề này khi sử dụng AmazonS3Client, nhúng Apache HTTPClient 4.1, bạn chỉ cần xác định một thuộc tính hệ thống như thế này để trình kiểm tra chứng chỉ SSL được thư giãn:

-Dcom.amazonaws.sdk.disableCertChecking = đúng

Quản lý nghịch ngợm


0

fwiw, một ví dụ sử dụng triển khai "Rest EAS" của JAX-RS 2.x để xây dựng một ứng dụng khách "tin tưởng tất cả" đặc biệt ...

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

phụ thuộc Maven liên quan

    <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

Nếu bạn đang sử dụng Apache httpClient 4.5.x thì hãy thử điều này:

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