如何忽略Apache HttpClient 4.0中的SSL证书错误


125

如何绕过Apache HttpClient 4.0 无效的SSL证书错误?


12
应该注意的是,这个问题的答案并没有超出要求的范围:它们让您忽略错误,但不能解决根本的问题(有点像从烟雾报警器中取出电池而不是扑灭火灾) )。证书的目的是确保SSL / TLS连接的安全性,忽略这些错误会导致MITM攻击漏洞。使用测试证书而不是忽略错误。
布鲁诺


46
“就像从烟雾报警器中取出电池一样”您可能会给其他开发人员带来疑问的好处,并假设他们知道自己在做什么。这个问题的动机可能是本地测试,OP希望进行快速测试,而无需经历设置简单SSL环境所需的大量Java样板。也许有人可以回答这个问题而不必参加“比你更重要”的演讲。
迈克

即在我们公司的内部JIRA服务器中有一些“基于Windows安全策略的证书”,该证书在域中包含的Windows计算机上有效,而在其他计算机上无效。我无法控制此策略,仍然想调用JIRA REST API。
odiszapc

1
@Bruno在处理小型厨房火灾时,无法在30至60分钟的时间内禁用烟雾探测器,这表明某些法律官员在某种程度上疯狂地缺乏对使用方式的洞察力,这在我看来与罪犯有界限。存在“从烟雾报警器中取出电池”这一概念的事实证明了这一点。对于必须获得证书才能进行简单测试的情况,我感到同样的愤怒,我知道这不会带来安全后果。这个问题的存在证明了这一点。
比尔K,

Answers:


84

您需要使用自己的TrustManager创建SSLContext,并使用此上下文创建HTTPS方案。这是代码,

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
假设我不想为我的网站购买有效的SSL证书,而只想使用它,那么这段代码可以提供帮助吗?为什么我看不到需要URL或需要异常处理的任何部分?
越南,

19
嗯,这是在告诉我“新的SSLSocketFactory(ssslCont)”正在使用KeyStore,而不是SSLContext。我想念什么吗?
MSpeed 2012年

2
我收到一个错误,指出X509TrustManager无法转换为TrustManager。
兆瓦。

2
确保您导入了正确的软件包,即从org.apache.http。
监狱长,

2
有谁知道如何将所有这些放在一起HttpClientBuilder
阿里

112

所有其他答案都已弃用或不适用于HttpClient 4.3。

这是构建http客户端时允许所有主机名的一种方法。

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

或者,如果您使用的是版本4.4或更高版本,则更新后的调用如下所示:

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

感谢您的回答,我想知道我在Android compile(“ org.apache.httpcomponents:httpclient:4.3.4”)中使用的是哪个包中的HttpsClients,但此类不会出现。
Juan Saravia 2014年

1
它的包是org.apache.http.impl.client.HttpClients。
erversteeg 2014年

14
这可以解决主机名不匹配(我认为)的问题,但是当证书不是由受信任的权威机构签名时,它似乎不起作用。
twm

1
@twm这就是为什么它说“允许所有主机名”的原因,信任问题需要不同的配置。
eis

1
@eis,我指出的是,此答​​案在某些情况下解决了原始问题,但在其他情况下却没有解决。
twm

43

只需使用较新的HttpClient 4.5来执行此操作,似乎它们自4.4起就已弃用了一些功能,因此这是适用于我并使用最新API的代码段:

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

工作对我来说也是HttpClient的4.5.2
维卡斯兰詹

这是HttpClient 4.5的最新消息
您很棒,

31

仅作记录,使用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
您是否在此示例中缺少一些代码?也许调用httpClient.set ...?
灰色,

6
httpclient.getConnectionManager()。getSchemeRegistry()。register(new Scheme(“ https”,443,sslsf));
本·弗林

8
SSLSocketFactory已在HttpClient 4.3中弃用
Toilal'1

1
如果使用Java 8,您甚至可以new SSLSocketFactory((chain, authType) -> true);
jlb 2015年

28

Apache HttpClient 4.5.5

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

没有使用过时的API。

简单的可验证测试用例:

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

谢谢!只要改变TrustAllStrategy.INSTANCETrustSelfSignedStrategy.INSTANCE在这个答案。
Percy Vega

这对我不起作用。javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX路径构建失败:sun.security。provider.certpath.SunCertPathBuilderException:无法找到到所请求目标的有效证书路径
ggb667

26

作为记录,已使用httpclient 4.3.6测试并与fluent api的Executor兼容:

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向上,你不得不这样做-而且还可能需要创建一个SSLConnectionSocketFactory使用SSLContext,并在定义这个Registry<ConnectionSocketFactory>,如果你要创建一个PoolingHttpClientConnectionManager。其他答案更受欢迎,但不适用于HttpClient 4.4。
Thomas W

1
与httpclient-4.3.5.jar完全一样地工作。
哈拉尔德

18

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

这是从我们实际的工作实现中提取的。

其他答案很流行,但是对于HttpClient 4.4,它们不起作用。我花了数小时尝试并竭尽全力,但似乎在4.4上发生了非常重大的API更改和重定位。

另请参见稍微完整的解释:http : //literatejava.com/networks/ignore-ssl-certificate-errors-apache-httpclient-4-4/

希望有帮助!


2
我就是我需要的SSLContext位。非常有义务。
muttonUp

14

如果您要做的是摆脱无效的主机名错误,则可以执行以下操作:

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

8
从4.1开始不推荐使用sf.setHostnameVerifier方法。替代方法是使用构造函数之一。例如:SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
kaliatech

当我不得不处理遗留代码时,这非常有用。
DuncanSungWKim 2015年

9

我们使用的是HTTPClient 4.3.5,我们尝试了几乎所有解决方案都存在于stackoverflow上,但是什么也没有,在思考并找出问题之后,我们得出了下面的代码,它们非常有效,只需在创建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);

以正常形式继续您的请求


7

使用流利的4.5.2,我必须进行以下修改才能正常工作。

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
这是唯一对我有用的解决方案。在升级到4.5之前,我尝试了上述针对4.3和4.4的解决方案。
dirkoneill '16

6

这就是我的做法-

  1. 创建我自己的MockSSLSocketFactory(下面附有类)
  2. 用它来初始化DefaultHttpClient。如果使用代理,则需要提供代理设置。

初始化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);

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

如果是代理人,则需要这样做-

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

如果将来包括这些导入内容,将会有所帮助。有两个不同的类。
AndroidDev

4

作为ZZ Coder答案的扩展,最好覆盖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 {
    }
});
// ...

您只需做即可达到相同的目的sf.setHostnameVerifier(new AllowAllHostnameVerifier());
Dan Dyer

7
从4.1开始不推荐使用sf.setHostnameVerifier。替代方法是使用构造函数之一。例如: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中的所有证书,可以在创建httpClient时使用以下一种衬里:

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

我得到这个:原因:javax.net.ssl.SSLHandshakeException:java.security.cert.CertificateException:没有主题替代名称吗?

如何在HttpClient API或RestClient API中允许没有证书的SSL站点连接?

4

使用Fluent API在HttpClient 4.5.5中进行了测试

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

下面的代码适用于 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()));
    }
}

代码的输出是

码

浏览器上的输出是

SSL错误

使用的pom在下面

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

感谢您提供的最新答案,我将悬赏奖励给了新来的人“欢迎”,但我只是想为大家提供最新的答案!

1
@feelingunwelcome,当然。我也对他表示支持:-)
塔伦·

2

Apache HttpClient 4.1.3的完整工作版本(基于上面的oleg代码,但在我的系统上仍需要allow_all_hostname_verifier):

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

注意,我将抛出所有异常,因为实际上,如果在实际系统中任何失败都将无能为力!


2

如果您使用的是Fluent API,则需要通过以下命令进行设置Executor

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

...如ZZ Coder的答案sslContext所示,在何处创建了SSLContext 。

之后,您可以按照以下方式执行http请求:

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

注意:已通过HttpClient 4.2测试


不幸的是在4.3中不推荐使用:“不推荐使用。(4.3)不要使用。”
STM

2

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

}


如果要这样做,如何在标题中设置值?

2

在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

如果您在使用嵌入Apache HttpClient 4.1的AmazonS3Client时遇到此问题,则只需要定义一个这样的系统属性即可放宽SSL证书检查器:

-Dcom.amazonaws.sdk.disableCertChecking = true

恶作剧管理


0

首先,使用JAX-RS 2.x的“ RestEasy”实现来构建特殊的“信任所有人”客户端的示例...

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

相关的Maven依赖项

    <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,请尝试以下操作:

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();
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.