java - Apache HttpClient 4.3 में SSL प्रमाणपत्र को अनदेखा करना




apache-httpcomponents (10)

Apache HttpClient 4.3 के लिए SSL प्रमाणपत्र (सभी पर विश्वास करें) को अनदेखा कैसे करें?

एसओ पर पिछले सभी संस्करणों को मैंने पाया है, और एपीआई बदल गया है।

सम्बंधित:

संपादित करें:

  • यह केवल परीक्षण उद्देश्यों के लिए है। बच्चे, घर पर (या उत्पादन में) कोशिश मत करो

(मैंने सीधे vasekt के उत्तर में एक टिप्पणी जोड़ दी होगी लेकिन मेरे पास पर्याप्त प्रतिष्ठा अंक नहीं हैं (निश्चित रूप से तर्क नहीं है)

वैसे भी ... मैं जो कहना चाहता था वह यह है कि भले ही आप पूलिंग कनेक्शन के लिए स्पष्ट रूप से निर्माण / मांग नहीं कर रहे हैं, इसका मतलब यह नहीं है कि आपको एक नहीं मिल रहा है।

मैं यह समझने की कोशिश कर पागल हो रहा था कि मूल समाधान मेरे लिए क्यों काम नहीं करता था, लेकिन मैंने वेसेक्ट के जवाब को नजरअंदाज कर दिया क्योंकि यह "मेरे मामले पर लागू नहीं हुआ" - गलत!

मैं अपने स्टैक-ट्रेस पर घूर रहा था जब कम और देखा मैंने इसके बीच में पूलिंग कनेक्शन देखा। बैंग - मैंने अपना जोड़ा और सफलता थक गई !! (हमारा डेमो कल है और मैं बेताब हो रहा था) :-)


@mavroprovato के उत्तर के अतिरिक्त, यदि आप केवल स्वयं हस्ताक्षरित होने के बजाय सभी प्रमाणपत्रों पर भरोसा करना चाहते हैं, तो आप करेंगे (आपके कोड की शैली में)

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

या (मेरे अपने कोड से सीधी प्रतिलिपि):

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

// ...

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

और यदि आप होस्टनाम सत्यापन को भी छोड़ना चाहते हैं, तो आपको सेट करने की आवश्यकता है

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

भी। (ALLOW_ALL_HOSTNAME_VERIFIER बहिष्कृत है)।

अनिवार्य चेतावनी: आपको वास्तव में ऐसा नहीं करना चाहिए, सभी प्रमाण पत्र स्वीकार करना एक बुरी बात है। हालांकि कुछ दुर्लभ उपयोग के मामले हैं जहां आप ऐसा करना चाहते हैं।

पहले दिए गए कोड को नोट के रूप में, यदि आप httpclient.execute () अपवाद फेंकते हैं तो भी आप प्रतिक्रिया बंद करना चाहेंगे

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

उपरोक्त कोड का उपयोग करके परीक्षण किया गया था

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

और रुचि के लिए, मेरा पूरा परीक्षण सेट यहां है:

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.junit.Test;

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

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

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

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

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

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

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

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

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

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

( जिथब में कार्य परीक्षण परियोजना)


Vasekt द्वारा जवाब के लिए एक छोटा सा जोड़ा:

PoolingHttpClientConnectionManager का उपयोग करते समय सॉकेट फैक्टरी रजिस्ट्री के साथ प्रदान किया गया समाधान काम करता है।

हालांकि, सादे http के माध्यम से कनेक्शन अब और काम नहीं करते हैं। आपको http प्रोटोकॉल के लिए अतिरिक्त रूप से फिर से काम करने के लिए एक PlainConnectionSocketFactory जोड़ना होगा:

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

अपाचे HTTP क्लाइंट में सभी कर्ट्स पर भरोसा करें

TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }
                        public void checkClientTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                        }
                        public void checkServerTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                        }
                    }
                };

          try {
                SSLContext sc = SSLContext.getInstance("SSL");
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
                SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                        sc);
                httpclient = HttpClients.custom().setSSLSocketFactory(
                        sslsf).build();
                HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

उपर्युक्त तकनीकों का एक कामकाजी आसवन यहां है, "curl --insecure" के समतुल्य:

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

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

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

यदि आप HttpClient 4.5.x का उपयोग कर रहे हैं, तो आपका कोड निम्न के जैसा हो सकता है:

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

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

विभिन्न विकल्पों का प्रयास करने के बाद, विन्यास के बाद http और https दोनों के लिए काम किया

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


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


        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
        cm.setMaxTotal(2000);//max connection


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

मैं http-client 4.3.3 का उपयोग कर रहा हूं -

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


सरल और छोटा कामकाजी कोड:

हम HTTPClient 4.3.5 का उपयोग कर रहे हैं और हमने स्टैक ओवरफ्लो पर लगभग सभी समाधान मौजूद हैं लेकिन कुछ भी नहीं, समस्या को समझने और समझने के बाद, हम निम्नलिखित कोड पर आते हैं जो पूरी तरह से काम करता है, बस इसे HttpClient उदाहरण बनाने से पहले जोड़ें।

कुछ विधि जो आप पोस्ट अनुरोध करने के लिए उपयोग करते हैं ...

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

    SSLConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(builder.build(),
            SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

    HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslSF).build();
    HttpPost postRequest = new HttpPost(url);

कॉलिंग जारी रखें और सामान्य रूप में HttpPost उदाहरण का उपयोग करें


नीचे दिया गया कोड स्व-हस्ताक्षरित प्रमाणपत्रों पर भरोसा करने के लिए काम करता है। अपने क्लाइंट को बनाते समय आपको TrustSelfSignedStrategy का उपयोग करना TrustSelfSignedStrategy :

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

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

मैंने उद्देश्य पर SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER शामिल नहीं किया था: बिंदु स्वयं हस्ताक्षरित प्रमाणपत्रों के साथ परीक्षण की अनुमति देना था ताकि आपको प्रमाणन प्राधिकरण से उचित प्रमाणपत्र प्राप्त न हो। आप आसानी से सही होस्ट नाम के साथ एक स्व-हस्ताक्षरित प्रमाणपत्र बना सकते हैं, इसलिए SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER ध्वज जोड़ने के बजाय ऐसा करें।


class ApacheHttpClient {

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

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

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

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

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

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

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




apache-httpcomponents