Cara mengabaikan kesalahan sertifikat SSL di Apache HttpClient 4.0


125

Bagaimana cara memintas kesalahan sertifikat SSL yang tidak valid dengan Apache HttpClient 4.0?


12
Perlu dicatat bahwa jawaban untuk pertanyaan ini tidak melakukan lebih dari yang diminta: mereka membiarkan Anda mengabaikan kesalahan tetapi tidak memperbaiki masalah mendasar (sedikit seperti melepas baterai dari alarm asap daripada memadamkan api ). Sertifikat memiliki tujuan untuk memastikan keamanan koneksi SSL / TLS, mengabaikan kesalahan yang menyebabkan kerentanan terhadap serangan MITM. Gunakan sertifikat uji alih-alih mengabaikan kesalahan.
Bruno


46
"seperti melepas baterai dari alarm asap" Anda mungkin memberi pengembang lain manfaat dari keraguan dan menganggap mereka tahu apa yang mereka lakukan. Mungkin motivasi untuk pertanyaan ini adalah pengujian lokal dan OP ingin menjalankan tes cepat tanpa melalui jumlah Java boilerplate yang diperlukan untuk mengatur bahkan lingkungan SSL sederhana. Mungkin seseorang bisa saja menjawab pertanyaan tanpa pergi ke kuliah "lebih suci dari kamu".
Mike

Yaitu di server JIRA internal perusahaan kami memiliki beberapa "sertifikat berbasis kebijakan keamanan windows" yang berlaku pada mesin Windows yang termasuk dalam domain dan tidak berlaku pada yang lain. Saya tidak bisa mengendalikan kebijakan ini dan masih ingin menelepon JIRA REST API.
odiszapc

1
@ Bruno Ketidakmampuan untuk menonaktifkan detektor asap untuk jangka waktu 30-60 menit saat berurusan dengan api dapur kecil menunjukkan kurangnya wawasan tentang pola penggunaan oleh beberapa pejabat hukum di beberapa titik yang saya merasa berbatasan dengan kriminal. Fakta bahwa ada konsep "mengeluarkan baterai dari alarm asap" membuktikan hal ini. Saya merasakan tingkat kemarahan yang sama karena harus mendapatkan sertifikat untuk bekerja untuk tes sederhana yang saya tahu tidak memiliki konsekuensi keamanan. Keberadaan pertanyaan ini membuktikan hal ini.
Bill K

Jawaban:


84

Anda perlu membuat konteks SSLC dengan TrustManager Anda sendiri dan membuat skema HTTPS menggunakan konteks ini. Ini kodenya,

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
Katakanlah saya tidak ingin membeli sertifikat SSL yang valid untuk situs saya dan hanya ingin menggunakannya, kode ini dapat membantu? Kenapa saya tidak melihat bagian di mana URL dibutuhkan atau penanganan pengecualian diperlukan?
Viet

19
Hmm, ia memberi tahu saya bahwa 'SSLSocketFactory baru (ssslCont)' mengharapkan KeyStore, bukan SSLContext. Apakah saya melewatkan sesuatu?
MSpeed

2
Saya mendapatkan kesalahan bahwa X509TrustManager tidak dapat dilemparkan ke TrustManager.
MW.

2
Pastikan Anda mengimpor paket yang benar, yaitu dari org.apache.http.
Sipir

2
Adakah yang tahu cara melempar semua ini menggunakan HttpClientBuilder?
Ali

112

Semua jawaban lain sudah usang atau tidak berfungsi untuk HttpClient 4.3.

Berikut adalah cara untuk mengizinkan semua nama host saat membuat klien http.

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

Atau jika Anda menggunakan versi 4.4 atau lebih baru, panggilan yang diperbarui terlihat seperti ini:

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

Terima kasih atas jawabannya, saya ingin tahu dari paket mana HttpsClients seperti yang saya gunakan dalam kompilasi Android ("org.apache.httpcomponents: httpclient: 4.3.4") tetapi kelas ini tidak muncul.
Juan Saravia

1
Paketnya adalah org.apache.http.impl.client.HttpClients.
erversteeg

14
Ini berfungsi di sekitar ketidakcocokan nama host (saya berasumsi), tetapi tampaknya tidak berfungsi ketika sertifikat tidak ditandatangani oleh otoritas tepercaya.
twm

1
@ twm itu sebabnya ia mengatakan "memungkinkan semua nama host", masalah kepercayaan memerlukan konfigurasi yang berbeda.
eis

1
@ ya, saya menunjukkan bahwa jawaban ini membahas pertanyaan awal dalam beberapa kasus tetapi tidak pada yang lain.
twm

43

Hanya harus melakukan ini dengan HttpClient 4.5 yang lebih baru dan sepertinya mereka sudah mencabut beberapa hal sejak 4.4 jadi inilah cuplikan yang berfungsi untuk saya dan menggunakan API terbaru:

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

Bekerja untuk saya juga untuk httpclient 4.5.2
Vikas Ranjan

yang ini adalah yang terbaru untuk HttpClient 4.5
Anda luar biasa

31

Sebagai catatan, ada cara yang lebih sederhana untuk mencapai hal yang sama dengan 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
Apakah Anda kehilangan beberapa kode dalam sampel ini? Mungkin panggilan ke httpClient.set ...?
Gray

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

8
SSLSocketFactory sudah tidak digunakan lagi di HttpClient 4.3
Toilal

1
Jika menggunakan Java 8, Anda dapatnew 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();

Tidak ada API usang yang digunakan.

Kasus uji sederhana yang dapat diverifikasi:

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

Terima kasih! Ubah saja TrustAllStrategy.INSTANCEdengan TrustSelfSignedStrategy.INSTANCEjawaban ini.
Percy Vega

Ini tidak berhasil untuk saya. javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: gagal membangun jalur PKIX: sun.security. provider.certpath.SunCertPathBuilderException: tidak dapat menemukan jalur sertifikasi yang valid ke target yang diminta
ggb667

26

Sebagai catatan, diuji dengan httpclient 4.3.6 dan kompatibel dengan Pelaksana api fasih:

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
Untuk HttpClient 4.4 ke atas, Anda harus melakukan ini - dan mungkin juga perlu membuat SSLConnectionSocketFactorymenggunakan itu SSLContext, dan mendefinisikan ini dalam Registry<ConnectionSocketFactory>, jika Anda akan membuat PoolingHttpClientConnectionManager. Jawaban lain lebih populer, tetapi tidak berfungsi di HttpClient 4.4.
Thomas W

1
Bekerja persis seperti ini dengan httpclient-4.3.5.jar.
Harald

18

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

Ini diambil dari implementasi kerja kami yang sebenarnya.

Jawaban lain populer, tetapi untuk HttpClient 4.4 mereka tidak berfungsi. Saya menghabiskan berjam-jam mencoba & melelahkan kemungkinan, tetapi tampaknya ada perubahan API sangat besar & relokasi di 4.4.

Lihat juga penjelasan yang sedikit lebih lengkap di: http://literatejava.com/networks/ignore-ssl-certificate-errors-apache-httpclient-4-4/

Semoga itu bisa membantu!


2
Saya adalah yang sedikit saya butuhkan SSLContext. Sangat wajib.
muttonUp

14

Jika semua yang ingin Anda lakukan adalah menyingkirkan kesalahan hostname yang tidak valid, Anda bisa melakukan:

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

8
Metode sf.setHostnameVerifier telah ditinggalkan pada 4.1. Alternatifnya adalah menggunakan salah satu konstruktor. Misalnya:SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
kaliatech

Ini sangat berguna ketika saya harus berurusan dengan kode warisan.
DuncanSungWKim

9

Kami menggunakan HTTPClient 4.3.5 dan kami mencoba hampir semua solusi yang ada di stackoverflow tetapi tidak ada, Setelah berpikir dan mencari tahu masalahnya, kami sampai pada kode berikut yang bekerja dengan sempurna, tambahkan saja sebelum membuat contoh HttpClient.

beberapa metode untuk menelepon ketika membuat permintaan posting ....

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

lanjutkan permintaan Anda dalam bentuk normal


7

Dengan fasih 4.5.2 saya harus membuat modifikasi berikut untuk membuatnya berfungsi.

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
Ini adalah satu-satunya solusi yang berhasil untuk saya. Saya mencoba solusi di atas untuk 4.3 dan 4.4 sebelum meningkatkan ke 4.5 dan mencoba ini.
dirkoneill

6

Ini adalah bagaimana saya melakukannya -

  1. Buat MockSSLSocketFactory sendiri (Kelas terlampir di bawah)
  2. Gunakan untuk menginisialisasi DefaultHttpClient. Pengaturan proxy perlu disediakan jika proxy digunakan.

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

Pabrik SSL Mock -

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

Jika di belakang proxy, perlu melakukan ini -

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

Ini akan membantu jika Anda memasukkan impor di masa depan. Ada dua kelas yang berbeda.
AndroidDev

4

Sebagai tambahan untuk jawaban ZZ Coder, akan lebih baik jika mengganti hostnameverifier.

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

Anda dapat mencapai hal yang sama dengan hanya melakukansf.setHostnameVerifier(new AllowAllHostnameVerifier());
Dan Dyer

7
Sf.setHostnameVerifier telah ditinggalkan pada 4.1. Alternatifnya adalah menggunakan salah satu konstruktor. Misalnya: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

Untuk menerima semua sertifikat di HttpClient 4.4.x Anda dapat menggunakan liner berikut saat membuat httpClient:

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

Saya mendapatkan ini: Disebabkan oleh: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Tidak ada nama alternatif subjek yang hadir?

Bagaimana cara mengizinkan koneksi ke situs SSL tanpa sertifikat di HttpClient API atau di RestClient API?

4

Diuji dengan HttpClient 4.5.5 dengan Fluent API

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

Kode di bawah ini berfungsi dengan 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()));
    }
}

Output dari kode adalah

Kode

Output pada browser adalah

SSL salah

Pom yang digunakan di bawah ini

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

terima kasih atas jawaban yang diperbarui, saya menghadiahkan hadiah kepada orang baru itu untuk "menyambut" tetapi saya hanya ingin jawaban yang diperbarui untuk semua orang!

1
@ merasa diterima, tentu saja. Saya telah mengangkatnya juga :-)
Tarun Lalwani

2

versi lengkap untuk Apache HttpClient 4.1.3 (berdasarkan kode oleg di atas, tetapi masih membutuhkan allow_all_hostname_verifier di sistem saya):

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

Catatan saya melemparkan kembali semua pengecualian karena sungguh, tidak banyak yang bisa saya lakukan jika semua ini gagal dalam sistem nyata!


2

Jika Anda menggunakan API yang lancar , Anda harus mengaturnya melalui Executor:

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

... di mana sslContextkonteks SSLC dibuat seperti yang ditunjukkan dalam jawaban ZZ Coder .

Setelah itu, Anda dapat melakukan permintaan http Anda sebagai:

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

Catatan: diuji dengan HttpClient 4.2


Sayangnya tidak digunakan lagi di 4.3: "Sudah usang. (4.3) jangan gunakan."
STM

2

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

}


Bagaimana cara menetapkan nilai di Header jika saya ingin melakukan itu?

2

Diuji pada 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

Jika Anda mengalami masalah ini saat menggunakan AmazonS3Client, yang menyematkan Apache HttpClient 4.1, Anda hanya perlu mendefinisikan properti sistem seperti ini sehingga pemeriksa sertifikat SSL santai:

-Dcom.amazonaws.sdk.disableCertChecking = true

Mischief berhasil


0

fwiw, contoh menggunakan implementasi "RestEasy" dari JAX-RS 2.x untuk membangun klien "kepercayaan semua" khusus ...

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

dependensi Maven terkait

    <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

Jika Anda menggunakan Apache httpClient 4.5.x maka coba ini:

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();
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.