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

如何使用 Apache HttpClient4.0绕过无效的 SSL 证书错误?

321614 次浏览

您需要使用自己的 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);

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

如果你只是想摆脱无效的主机名错误,你可以这样做:

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

仅供记录,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;
}


});

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

注意,我要重新引发所有异常,因为实际上,如果在实际系统中这些异常中的任何一个失败,我都无能为力!

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

我就是这么做的

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

初始化默认 HTTPClient-

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

如果您在使用嵌入 Apache HttpClient 4.1的 AmazonS3Client 时遇到这个问题,您只需定义一个系统属性,如下所示,以便放松 SSL 证书检查器:

- Dcom.amazonaws.sdk.disableCertChecking = true

恶作剧解决了

如果你正在使用 流畅的空气污染指数,你需要通过 Executor设置它:

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

... 其中 sslContext是如 ZZ 编码器的答案所示创建的 SSLContext。

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

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

注意: 使用 HttpClient 4.2进行了测试

所有其他的答案要么不被推荐使用,要么不适用于 HttpClient 4.3。

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

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

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

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

用4.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;
}

}

对于记录,使用 httpclient 4.3.6进行测试,并与流畅 API 的 Execector 兼容:

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

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

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

其他的答案很流行,但是对于 HttpClient4.4来说它们不起作用。我花了好几个小时尝试和耗尽的可能性,但似乎有极其重大的 API 变化和重新安置在4.4。

请参阅更详细的说明: http://literatejava.com/networks/ignore-ssl-certificate-errors-apache-httpclient-4-4/

希望能帮上忙!

我们正在使用 HTTPClient4.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);

以正常形式继续您的请求

要接受 HttpClient 4.4.x 中的所有证书,您可以在创建 httpClient 时使用以下一行:

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

这是一个使用 JAX-RS 2.x 的“ RestEasy”实现构建特殊的“ trust all”客户机的示例..。

    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>

只是不得不对新的 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();

在流畅的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) {
}

在4.5.4上测试:

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


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

使用 HttpClient4.5.5和 FluentAPI 进行测试

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

如果你正在使用 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();
}

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

代码的输出为

Code

浏览器的输出为

Bad SSL

所使用的吊球在下面

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

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