如何使用Apache HttpClient 4.0绕过无效的SSL证书错误?
如何使用Apache HttpClient 4.0绕过无效的SSL证书错误?
其他所有答案都已被弃用或无法在HttpClient 4.3中使用。
以下是一种构建http客户端并允许所有主机名的方法。
CloseableHttpClient httpClient = HttpClients
.custom()
.setHostnameVerifier(new AllowAllHostnameVerifier())
.build();
如果您正在使用4.4版本或更高版本,则更新后的调用看起来像这样:
CloseableHttpClient httpClient = HttpClients
.custom()
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
您需要使用自己的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);
HttpClientBuilder
将所有这些东西组合起来吗? - AliApache 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.INSTANCE
更改为 TrustSelfSignedStrategy.INSTANCE
。 - Percy VegaTrustAllStrategy.INSTANCE
,但我尝试自己实现它:new SSLContextBuilder().loadTrustMaterial(null, (chain, authType) -> true).build()
,并且它已经起作用了。 - Svichkarev Anatoly我最近使用了更新的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.1可以更简单地实现同样的功能。
SSLSocketFactory sslsf = new SSLSocketFactory(new TrustStrategy() {
public boolean isTrusted(
final X509Certificate[] chain, String authType) throws CertificateException {
// Oh, I am easy...
return true;
}
});
new SSLSocketFactory((chain, authType) -> true);
。 - jlb记录一下,使用 httpclient 4.3.6 进行测试,并兼容流畅 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();
SSLContext
创建一个 SSLConnectionSocketFactory
,并在 Registry<ConnectionSocketFactory>
中定义它,如果你要创建一个 PoolingHttpClientConnectionManager
。其他答案更受欢迎,但在 HttpClient 4.4 上不起作用。 - Thomas WHttpClientBuilder 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/
希望这有所帮助!
如果您只想消除无效主机名错误,您可以执行以下操作:
HttpClient httpClient = new DefaultHttpClient();
SSLSocketFactory sf = (SSLSocketFactory)httpClient.getConnectionManager()
.getSchemeRegistry().getScheme("https").getSocketFactory();
sf.setHostnameVerifier(new AllowAllHostnameVerifier());
SSLSocketFactory sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
- kaliatech在进行POST请求时调用的某些方法...
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);
在使用fluent 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) {
}