简介【HttpClient高级进阶-SSL】本文将展示如何使用“全部接受”SSL支持配置Apache HttpClient 4 。目标很简单 - 使用没有有效证书的HTTPS URL 。
SSLPeerUnverifiedException如果不使用HttpClient配置SSL,以下测试(使用HTTPS URL)将失败:
public class RestClientLiveManualTest {@Test(expected = SSLPeerUnverifiedException.class) public void test()throws ClientProtocolException, IOException {CloseableHttpClient httpClient = HttpClients.createDefault(); String urlOverHttps ="https://localhost:8082/httpclient-simple)";HttpGet getMethod = new HttpGet(urlOverHttps);HttpResponse response = httpClient.execute(getMethod); assertThat(response.getStatusLine().getStatusCode(), equalTo(200)); }}异常报错为:
JAVAx.net.ssl.SSLPeerUnverifiedException: peer not authenticated at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:397) at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:126) ...该
javax.net.ssl.SSLPeerUnverifiedException,该报错产生原因,当无法有效为URL建立信任链的时候 。
配置通用的SSL(HttpClient <4.3)现在让我们将HTTPClient配置为信任所有证书,无论其有效性如何:
@Testpublic final void test()throws GeneralSecurityException { HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); CloseableHttpClient httpClient = (CloseableHttpClient) requestFactory.getHttpClient();TrustStrategy acceptingTrustStrategy = (cert, authType) -> true; SSLSocketFactory sf = new SSLSocketFactory(acceptingTrustStrategy, ALLOW_ALL_HOSTNAME_VERIFIER); httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", 8443, sf));ResponseEntity<String> response = new RestTemplate(requestFactory). exchange(urlOverHttps, HttpMethod.GET, null, String.class); assertThat(response.getStatusCode().value(), equalTo(200));}随着acceptingTrustStrategy 配置了 true的测试通过,client能够消费的HTTPS URL 。
配置通用的SSL(HttpClient 4.4及更高版本)使用新的HTTPClient,现在我们有了一个增强的,重新设计的默认SSL主机名验证程序 。此外,通过引入
SSLConnectionSocketFactory和RegistryBuilder,可以轻松构建SSLSocketFactory 。所以我们可以编写上面的测试用例,如:
@Testpublic final void test() throws GeneralSecurityException { TrustStrategy acceptingTrustStrategy = (cert, authType) -> true; SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE);Registry<ConnectionSocketFactory> socketFactoryRegistry =RegistryBuilder.<ConnectionSocketFactory> create() .register("https", sslsf) .register("http", new PlainConnectionSocketFactory()) .build();BasicHttpClientConnectionManager connectionManager =new BasicHttpClientConnectionManager(socketFactoryRegistry); CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf) .setConnectionManager(connectionManager).build();HttpComponentsClientHttpRequestFactory requestFactory =new HttpComponentsClientHttpRequestFactory(httpClient); ResponseEntity<String> response = new RestTemplate(requestFactory) .exchange(urlOverHttps, HttpMethod.GET, null, String.class); assertThat(response.getStatusCode().value(), equalTo(200));}使用SSL 的Spring RestTemplate(HttpClient <4.3)现在我们已经了解了如何配置具有SSL支持的原始HttpClient,让我们来看看更高级别的方式-Spring RestTemplate 。
如果未配置SSL,则以下测试将按预期会抛异常:
@Test(expected = ResourceAccessException.class)public void test() { String urlOverHttps= "https://localhost:8443/httpclient-simple/api/bars/1"; ResponseEntity<String> response= new RestTemplate().exchange(urlOverHttps, HttpMethod.GET, null, String.class); assertThat(response.getStatusCode().value(), equalTo(200));}那么让我们配置SSL:
@Testpublic void test()throws GeneralSecurityException { HttpComponentsClientHttpRequestFactory requestFactory= new HttpComponentsClientHttpRequestFactory(); DefaultHttpClient httpClient = (DefaultHttpClient) requestFactory.getHttpClient(); TrustStrategy acceptingTrustStrategy = (cert, authType) -> true SSLSocketFactory sf = new SSLSocketFactory( acceptingTrustStrategy, ALLOW_ALL_HOSTNAME_VERIFIER); httpClient.getConnectionManager().getSchemeRegistry() .register(new Scheme("https", 8443, sf));String urlOverHttps ="https://localhost:8443/httpclient-simple/api/bars/1"; ResponseEntity<String> response = new RestTemplate(requestFactory). exchange(urlOverHttps, HttpMethod.GET, null, String.class); assertThat(response.getStatusCode().value(), equalTo(200));}这与我们为原始HttpClient配置SSL的方式非常相似 - 我们使用SSL支持配置请求工厂,然后我们实例化通过此预配置工厂的模板 。
推荐阅读
- 索尼|索尼招聘PC平台高级主管!玩家:吃了秤砣铁了心要搞PC?
- 翡翠|什么样的翡翠绿色最高级?
- Python进阶记录之HTMLParser模块
- 中高级前端必须注意的40条移动端H5坑位指南
- 人生最高级的活法是享受孤独?人活到极致-会赚钱,能独处,常读书
- 中越战争牺牲的21名团级军官 对越自卫反击战牺牲的高级军官
- 穿衣搭配|学习博主的“一周穿搭”,气质高级又时髦,大家一定照着学
- ps画笔的高级用法,它很重要,顺便利用这个知识点修个眉毛
- 界面该不该加弹窗?来看高级设计师的总结
- quickly的比较级和最高级?slowly的比较级和最高级