How to ignore SSL certificate errors in Apache HttpClient 4.0
如何绕过Apache HttpClient 4.0的无效SSL证书错误?
所有其他答案都已弃用或不适用于HttpClient 4.3。
这是构建http客户端时允许所有主机名的一种方法。
1 2 3 4 | CloseableHttpClient httpClient = HttpClients .custom() .setHostnameVerifier(AllowAllHostnameVerifier.INSTANCE) .build(); |
或者,如果您使用的是版本4.4或更高版本,则更新后的调用如下所示:
1 2 3 4 | CloseableHttpClient httpClient = HttpClients .custom() .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) .build(); |
您需要使用自己的TrustManager创建SSLContext并使用此上下文创建HTTPS方案。这是代码,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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); |
只需使用较新的HttpClient 4.5来执行此操作,似乎它们从4.4开始就已弃用了一些功能,因此这是适用于我并使用最新API的代码段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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可以轻松得多
1 2 3 4 5 6 7 8 9 | 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.5.5
1 2 3 4 5 | HttpClient httpClient = HttpClients .custom() .setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, TrustAllStrategy.INSTANCE).build()) .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) .build(); |
没有使用过时的API。
简单的可验证测试用例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | 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; } } |
作为记录,已通过httpclient 4.3.6测试并与fluent api的Executor兼容:
1 2 3 4 5 6 7 8 9 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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/
希望有帮助!
如果您要做的是摆脱无效的主机名错误,则可以执行以下操作:
1 2 3 4 | HttpClient httpClient = new DefaultHttpClient(); SSLSocketFactory sf = (SSLSocketFactory)httpClient.getConnectionManager() .getSchemeRegistry().getScheme("https").getSocketFactory(); sf.setHostnameVerifier(new AllowAllHostnameVerifier()); |
我们正在使用HTTPClient 4.3.5,并且我们尝试了几乎所有解决方案都存在于stackoverflow上,但是没有任何解决方案,
在思考并找出问题所在之后,我们来看下面的代码,它们可以很好地工作,
只需在创建HttpClient实例之前添加它即可。
some method to call when making post requests....
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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); |
continue your request in the normal form
使用流利的4.5.2,我必须进行以下修改才能正常工作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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) { } |
这就是我的做法-
初始化DefaultHTTPClient-
1 2 3 4 5 6 | 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工厂-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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; } }; } |
如果是代理人,则需要这样做-
1 2 3 4 5 6 7 8 | 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)); |
要接受HttpClient 4.4.x中的所有证书,可以在创建httpClient时使用以下一种衬里:
1 | httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).setSslcontext(new SSLContextBuilder().loadTrustMaterial(null, (x509Certificates, s) -> true).build()).build(); |
作为ZZ Coder答案的扩展,最好覆盖hostnameverifier。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // ... 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 { } }); // ... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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); } |
使用Fluent API在HttpClient 4.5.5上进行了测试
1 2 3 4 5 6 7 8 9 10 11 | 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(); |
以下代码适用于
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | 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())); } } |
代码的输出是
浏览器上的输出是
使用的pom在下面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <?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> testing</artifactId> <version>1.0-SNAPSHOT</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> 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> httpclient</artifactId> <version>4.5.5</version> </dependency> </dependencies> </project> |
Apache HttpClient 4.1.3的完整工作版本(基于上面的oleg代码,但在我的系统上仍需要allow_all_hostname_verifier):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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); } } |
注意,我将重新抛出所有异常,因为实际上,如果在真实系统中任何失败都将无济于事!
经过4.3.3测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | 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; } |
}
如果使用的是流畅的API,则需要通过
1 2 3 4 | Executor.unregisterScheme("https"); SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); Executor.registerScheme(new Scheme("https", 443, sslSocketFactory)); |
...其中
之后,您可以按以下方式执行http请求:
1 2 |
注意:已通过HttpClient 4.2测试 sub>
在4.5.4上测试:
1 2 3 4 5 6 7 8 | SSLContext sslContext = new SSLContextBuilder() .loadTrustMaterial(null, (TrustStrategy) (arg0, arg1) -> true).build(); CloseableHttpClient httpClient = HttpClients .custom() .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) .setSSLContext(sslContext) .build(); |
首先,使用JAX-RS 2.x的" RestEasy"实现来构建特殊的"信任所有人"客户端的示例...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | 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依赖项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <dependency> <groupId>org.jboss.resteasy</groupId> resteasy-client</artifactId> <version>3.0.10.Final</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> jaxrs-api</artifactId> <version>3.0.10.Final</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> resteasy-jackson2-provider</artifactId> <version>3.0.10.Final</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> httpclient</artifactId> <version>4.5</version> <type>jar</type> </dependency> <dependency> <groupId>javax</groupId> javaee-web-api</artifactId> <version>7.0</version> <scope>provided</scope> </dependency> |
如果您在使用嵌入Apache HttpClient 4.1的AmazonS3Client时遇到此问题,则只需定义这样的系统属性,即可放宽SSL证书检查器:
-Dcom.amazonaws.sdk.disableCertChecking = true
恶作剧管理
如果您使用的是Apache httpClient 4.5.x,请尝试以下操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 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(); } |