Java 如何忽略 Apache HttpClient 4.0 中的 SSL 证书错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2703161/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to ignore SSL certificate errors in Apache HttpClient 4.0
提问by Viet
How do I bypass invalid SSL certificate errors with Apache HttpClient4.0?
如何使用 Apache HttpClient4.0绕过无效的 SSL 证书错误?
采纳答案by ZZ Coder
You need to create a SSLContext with your own TrustManager and create HTTPS scheme using this context. Here is the code,
您需要使用自己的 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);
回答by eldur
In extension to ZZ Coder's answerit will be nice to override the hostnameverifier.
作为ZZ Coder 答案的扩展,覆盖主机名验证器会很好。
// ...
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 {
}
});
// ...
回答by David Tinker
If all you want to do is get rid of invalid hostname errors you can just do:
如果您只想摆脱无效的主机名错误,您可以这样做:
HttpClient httpClient = new DefaultHttpClient();
SSLSocketFactory sf = (SSLSocketFactory)httpClient.getConnectionManager()
.getSchemeRegistry().getScheme("https").getSocketFactory();
sf.setHostnameVerifier(new AllowAllHostnameVerifier());
回答by ok2c
Just for the record, there is a much simpler way to accomplish the same with HttpClient 4.1
只是为了记录,有一种更简单的方法可以使用 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;
}
});
回答by Korny
a full working version for Apache HttpClient 4.1.3 (based on oleg's code above, but it still needed an allow_all_hostname_verifier on my system):
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);
}
}
Note I'm re-throwing all exceptions because really, there's not much I can do if any of this fails in a real system!
请注意,我正在重新抛出所有异常,因为实际上,如果其中任何一个在真实系统中失败,我无能为力!
回答by littletiger
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);
}
回答by Swaroop Rath
This is how I did it -
我就是这样做的——
- Create my own MockSSLSocketFactory (Class attached below)
- Use it to initialise DefaultHttpClient. Proxy settings need to be provided if a proxy is used.
- 创建我自己的 MockSSLSocketFactory(下面附有类)
- 使用它来初始化 DefaultHttpClient。如果使用代理,则需要提供代理设置。
Initialising 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);
Mock SSL Factory -
模拟 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;
}
};
}
If behind a proxy, need to do this -
如果在代理后面,需要这样做 -
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));
回答by Mike Slinn
If you encountered this problem when using AmazonS3Client, which embeds Apache HttpClient 4.1, you simply need to define a system property like this so that the SSL cert checker is relaxed:
如果您在使用嵌入 Apache HttpClient 4.1 的 AmazonS3Client 时遇到此问题,您只需定义一个像这样的系统属性,以便放松 SSL 证书检查器:
-Dcom.amazonaws.sdk.disableCertChecking=true
-Dcom.amazonaws.sdk.disableCertChecking=true
Mischief managed
恶作剧管理
回答by Elias Dorneles
If you are using the fluent API, you need to set it up via the Executor
:
如果您使用的是fluent API,则需要通过以下方式进行设置Executor
:
Executor.unregisterScheme("https");
SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslContext,
SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Executor.registerScheme(new Scheme("https", 443, sslSocketFactory));
... where sslContext
is the SSLContext created as shown in the ZZ Coder's answer.
...sslContext
创建的 SSLContext 在哪里,如ZZ Coder的回答所示。
After that, you can do your http requests as:
之后,您可以按以下方式执行 http 请求:
String responseAsString = Request.Get("https://192.168.1.0/whatever.json")
.execute().getContent().asString();
Note:tested with HttpClient 4.2
注意:使用 HttpClient 4.2 测试
回答by erversteeg
All of the other answers were either deprecated or didn't work for HttpClient 4.3.
所有其他答案都已弃用或不适用于 HttpClient 4.3。
Here is a way to allow all hostnames when building an http client.
这是一种在构建 http 客户端时允许所有主机名的方法。
CloseableHttpClient httpClient = HttpClients
.custom()
.setHostnameVerifier(AllowAllHostnameVerifier.INSTANCE)
.build();
Or if you are using version 4.4 or later, the updated call looks like this:
或者,如果您使用的是 4.4 或更高版本,则更新后的调用如下所示:
CloseableHttpClient httpClient = HttpClients
.custom()
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();