Apache HttpClient 4.0'da SSL sertifika hataları nasıl göz ardı edilir


126

Apache HttpClient 4.0 ile geçersiz SSL sertifika hatalarını nasıl atlarım ?


12
Bu sorunun yanıtlarının sorulandan daha fazlasını yapmadığı unutulmamalıdır: Hatayı görmezden gelmenize izin verirler ancak temeldeki sorunu çözmezler (biraz yangını söndürmek yerine pilleri bir duman alarmından çıkarmak gibi) ). Sertifikaların SSL / TLS bağlantısının güvenliğini sağlamada bir amacı vardır, bu hataların göz ardı edilmesi, MITM saldırısına bir güvenlik açığı getirir. Hatayı göz ardı etmek yerine test sertifikalarını kullanın.
Bruno


47
"pilleri bir duman alarmından çıkarmak gibi" Diğer geliştiricilere şüpheden fayda sağlayabilir ve ne yaptıklarını bildiklerini varsayabilirsiniz. Belki de bu sorunun motivasyonu yerel testtir ve OP, basit bir SSL ortamı kurmak için gerekli olan korkunç miktardaki Java standart metninden geçmeden hızlı bir test yapmak ister. Belki birisi "senden daha kutsal" dersine girmeden soruyu cevaplayabilir.
Mike

Şirketimizin dahili JIRA sunucusunda, etki alanına dahil olan Windows makinelerinde geçerli olan ve diğerlerinde geçerli olmayan bazı "Windows güvenlik ilkesi tabanlı sertifikaları" vardır. Bu politikayı kontrol edemiyorum ve yine de JIRA REST API'yi çağırmak istiyorum.
odiszapc

1
@Bruno Küçük bir mutfak yangını ile uğraşırken duman dedektörlerini 30-60 dakikalık bir süre devre dışı bırakamama, bazı yasal görevlilerin kullanım şekillerine dair delice bir kavrayış eksikliğini gösteriyor ve bir noktada suçlu hissettiğim bir noktada. Bir "duman alarmından pillerin çıkarılması" konseptinin olması bunu kanıtlıyor. Güvenlik sonuçları olmadığını bildiğim basit bir test için çalışmak için sertifika almak zorunda olma konusunda aynı düzeyde öfke hissediyorum. Bu sorunun varlığı bunu kanıtlıyor.
Bill K

Yanıtlar:


84

Kendi TrustManager'ınızla bir SSLContext oluşturmanız ve bu bağlamı kullanarak HTTPS şeması oluşturmanız gerekir. İşte kod,

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
Sitem için geçerli bir SSL sertifikası satın almak istemediğimi ve sadece kullanmak istediğimi varsayalım, bu kod parçası yardımcı olabilir mi? Bir URL'nin gerekli olduğu veya istisna işlemenin gerekli olduğu herhangi bir bölümü neden görmüyorum?
Viet

19
Hmm, bana 'new SSLSocketFactory (ssslCont)' in bir SSLContext değil, bir KeyStore beklediğini söylüyor. Bir şey mi kaçırıyorum?
MSpeed

2
X509TrustManager'ın TrustManager'a dönüştürülemeyeceği hatasını alıyorum.
MW.

2
Doğru paketleri, yani org.apache.http'den içe aktardığınızdan emin olun.
müdür

2
Tüm bunları kullanarak nasıl bir araya getireceğini bilen var HttpClientBuildermı?
Ali

112

Diğer yanıtların tümü ya kullanımdan kaldırıldı ya da HttpClient 4.3 için çalışmadı.

İşte bir http istemcisi oluştururken tüm ana bilgisayar adlarına izin vermenin bir yolu.

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

Veya 4.4 veya sonraki bir sürümünü kullanıyorsanız, güncellenmiş çağrı şu şekilde görünür:

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

Cevabınız için teşekkürler, Android derlemesinde ("org.apache.httpcomponents: httpclient: 4.3.4") kullandığım için hangi paketin HttpsClients olduğunu bilmek istiyorum ancak bu sınıf görünmüyor.
Juan Saravia

1
Paket org.apache.http.impl.client.HttpClients şeklindedir.
erversteeg

14
Bu, bir ana bilgisayar adı uyuşmazlığı etrafında çalışır (sanırım), ancak sertifika güvenilir bir yetkili tarafından imzalanmadığında çalışmıyor gibi görünüyor.
twm

1
@twm bu yüzden "tüm ana bilgisayar adlarına izin veriyor" diyor, güven sorunları farklı yapılandırma gerektiriyor.
eis

1
@eis, bu cevabın bazı durumlarda orijinal soruya hitap ettiğini ancak diğerlerinde değil.
twm

43

Bunu daha yeni HttpClient 4.5 ile yapmak zorundaydım ve 4.4'ten beri birkaç şeyi kullanımdan kaldırmış gibi görünüyorlar, işte benim için çalışan ve en son API'yi kullanan snippet:

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

Benim için de httpclient 4.5.2 için çalıştı
Vikas Ranjan

bu HttpClient 4.5 için güncel
Harikasınız

31

Sadece kayıt için, HttpClient 4.1 ile aynı şeyi başarmanın çok daha basit bir yolu var.

    SSLSocketFactory sslsf = new SSLSocketFactory(new TrustStrategy() {

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

    });

1
Bu örnekte bazı kodlar eksik mi? Belki httpClient.set'e bir çağrı ...?
Gray

6
httpclient.getConnectionManager (). getSchemeRegistry (). register (yeni Şema ("https", 443, sslsf));
Ben Flynn


1
Java 8 kullanıyorsanız, şunu da yapabilirsiniznew SSLSocketFactory((chain, authType) -> true);
jlb

31

Apache HttpClient 4.5.5

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

Kullanımdan kaldırılmış API kullanılmadı.

Basit doğrulanabilir test senaryosu:

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

Teşekkür ederim! Sadece değiştirmek TrustAllStrategy.INSTANCEile TrustSelfSignedStrategy.INSTANCEbu yanıtında.
Percy Vega

Bu benim için işe yaramadı. javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX yolu oluşturma başarısız: sun.security. provider.certpath.SunCertPathBuilderException: istenen hedef için geçerli sertifika yolu bulunamıyor
ggb667

Teşekkürler, Benim için sorunsuz çalıştı.
Sanjay Jain

26

Kayıt için httpclient 4.3.6 ile test edildi ve Executor of fluent api ile uyumlu:

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

3
HttpClient 4.4 ve üstü için, bunu yapmanız gerekir - ve bunu SSLConnectionSocketFactorykullanarak bir tane oluşturmanız SSLContextve Registry<ConnectionSocketFactory>bunu bir PoolingHttpClientConnectionManager. Diğer yanıtlar daha popülerdir, ancak HttpClient 4.4'te çalışmaz.
Thomas W

1
Httpclient-4.3.5.jar ile tam olarak böyle çalışır.
Harald

18

Apache HttpClient 4.4 için:

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

Bu, gerçek çalışma uygulamamızdan alınmıştır.

Diğer yanıtlar popülerdir, ancak HttpClient 4.4 için çalışmazlar. Olasılıkları denemek ve tüketmek için saatler harcadım, ancak 4.4'te son derece büyük API değişikliği ve yer değiştirmesi var gibi görünüyor.

Ayrıca biraz daha kapsamlı bir açıklamaya bakın: http://literatejava.com/networks/ignore-ssl-certificate-errors-apache-httpclient-4-4/

Umarım yardımcı olur!


2
İhtiyacım olan SSLContext bitiydim. Çok minnettarım.
muttonUp

14

Tek yapmak istediğiniz geçersiz ana bilgisayar adı hatalarından kurtulmaksa, şunları yapabilirsiniz:

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

8
Sf.setHostnameVerifier yöntemi 4.1 itibariyle kullanımdan kaldırılmıştır. Alternatif, kuruculardan birini kullanmaktır. Örneğin:SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
kaliatech

Eski kodla uğraşmak zorunda kaldığımda bu çok faydalı oldu.
DuncanSungWKim

9

HTTPClient 4.3.5 kullanıyoruz ve hemen hemen tüm çözümleri stackoverflow üzerinde denedik ama hiçbir şey yapmadık, Sorunu düşündükten ve çözdükten sonra, mükemmel çalışan aşağıdaki koda geliyoruz, HttpClient örneğini oluşturmadan önce eklemeniz yeterli.

gönderi talepleri yaparken aramak için bazı yöntemler ...

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

isteğinize normal biçimde devam edin


7

Akıcı 4.5.2 ile çalışması için aşağıdaki değişikliği yapmak zorunda kaldım.

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
Benim için işe yarayan tek çözüm bu. 4.5'e yükseltmeden ve bunu denemeden önce 4.3 ve 4.4 için yukarıdaki çözümleri denedim.
dirkoneill

6

Ben böyle yaptım -

  1. Kendi MockSSLSocketFactory'mi oluştur (Sınıf aşağıda eklenmiştir)
  2. DefaultHttpClient'i başlatmak için kullanın. Bir proxy kullanılıyorsa, proxy ayarlarının sağlanması gerekir.

DefaultHTTPClient başlatılıyor -

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

Sahte SSL Fabrikası -

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

Bir proxy'nin arkasındaysa, bunu yapmanız gerekir -

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

İleride ithalatı da dahil ederseniz yardımcı olur. İki farklı sınıf var.
AndroidDev

4

ZZ Coder'ın cevabının bir uzantısı olarak , hostnameverifier'ı geçersiz kılmak güzel olacaktır.

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

Aynı şeyi sadece yaparak da başarabilirsinizsf.setHostnameVerifier(new AllowAllHostnameVerifier());
Dan Dyer

7
Sf.setHostnameVerifier, 4.1 itibariyle kullanımdan kaldırılmıştır. Alternatif, kuruculardan birini kullanmaktır. Örneğin:SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
kaliatech

4
        DefaultHttpClient httpclient = new DefaultHttpClient();

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

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

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

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

4

HttpClient 4.4.x'teki tüm sertifikaları kabul etmek için, httpClient'i oluştururken aşağıdaki tek satırı kullanabilirsiniz:

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

Bunu alıyorum: Nedeni: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Konu alternatif adları yok mu?

HttpClient API veya RestClient API'de sertifikasız SSL sitelerine bağlantılara nasıl izin verilir?

4

Fluent API ile HttpClient 4.5.5 ile test edildi

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

Aşağıdaki kod ile çalışır 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()));
    }
}

Koddan çıktı

kod

Tarayıcıdaki çıktı

Kötü SSL

Kullanılan pom aşağıda

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

Güncellenen cevap için teşekkürler. Yeni adama "hoş geldiniz" ödülünü verdim ama sadece herkes için güncellenmiş cevaplar istedim!

1
@feelingunwelcome, tabii. Ona da olumlu oy verdim :-)
Tarun Lalwani

2

Apache HttpClient 4.1.3 için tam çalışan bir sürüm (yukarıdaki oleg koduna göre, ancak yine de sistemimde bir allow_all_hostname_verifier gerekiyordu):

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

Not Tüm istisnaları yeniden atıyorum çünkü gerçekten, bunların herhangi biri gerçek bir sistemde başarısız olursa yapabileceğim pek bir şey yok!


2

Fluent API kullanıyorsanız, bunu şu yolla kurmanız gerekir Executor:

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

... ZZ Coder'ınsslContext cevabında gösterildiği gibi oluşturulan SSLContext nerede .

Bundan sonra http isteklerinizi şu şekilde yapabilirsiniz:

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

Not: HttpClient 4.2 ile test edildi


Maalesef 4.3'te kullanımdan kaldırıldı: "Kullanımdan kaldırıldı. (4.3) kullanmayın."
STM

2

4.3.3 ile test edildi

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

}


Bunu yapmak istersem Başlıklar'da değerler nasıl ayarlanır?

2

4.5.4'te test edildi:

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

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

0

Apache HttpClient 4.1'i yerleştiren AmazonS3Client'i kullanırken bu sorunla karşılaştıysanız, SSL sertifika denetleyicisinin rahatlaması için bunun gibi bir sistem özelliği tanımlamanız yeterlidir:

-Dcom.amazonaws.sdk.disableCertChecking = true

Muziplik tamamlandı


0

fwiw, özel bir "herkese güven" istemcisi oluşturmak için JAX-RS 2.x'in "RestEasy" uygulamasını kullanan bir örnek ...

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

ilgili Maven bağımlılıkları

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

-1

Apache httpClient 4.5.x kullanıyorsanız, şunu deneyin:

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();
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.