Ssl Apache HttpClient自签名证书
自签名证书是指未经证书颁发机构(CA)签名的证书。JAVA存储了大部分CA的证书(这里是jre/lib/security/cacerts),因此,如果您想使用CA签名的证书连接到https站点,则没有专门的代码。(http调用的代码相同) 所以基本上Ssl Apache HttpClient自签名证书,ssl,apache-httpclient-4.x,self-signed,Ssl,Apache Httpclient 4.x,Self Signed,自签名证书是指未经证书颁发机构(CA)签名的证书。JAVA存储了大部分CA的证书(这里是jre/lib/security/cacerts),因此,如果您想使用CA签名的证书连接到https站点,则没有专门的代码。(http调用的代码相同) 所以基本上 CloseableHttpClient httpclient = HttpClients.createDefault(); HttpGet httpGet = new HttpGet(https_url); httpclient.execute(h
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(https_url);
httpclient.execute(httpGet)
但是如果我们有一个自签名证书,那么我们需要配置客户端并使其工作。否则我们会看到
sun.security.validator.ValidatorException:PKIX路径生成失败:sun.security.provider.certpath.SunCertPathBuilderException:找不到请求目标的有效证书路径
javax.net.ssl.SSLPeerUnverifiedException:主机名“localhost”与对等方提供的证书主题不匹配
如何为这种情况配置http客户端?httpclient 4.x
方法1
通过调试选项配置信任库
-Djavax.net.ssl.trustStore=/Users/amodpandey/.keystore
Java能够读取信任库,即使不传递密码(信任库的密码)
但即使在这之后,你也可能面临
javax.net.ssl.SSLPeerUnverifiedException:主机名“localhost”与对等方提供的证书主题不匹配
而且很有效
方法2
把一切都写进代码里
CloseableHttpClient httpClient =
HttpClientBuilder.create()
.setSslcontext(SSLContexts.custom().loadTrustMaterial(new File(Thread.currentThread().getContextClassLoader().getResource("keystore").getFile())).build())
.setSSLHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
})
.build();
方法3
在使用连接管理器时
使用时忽略setSslcontext和setSSLHostnameVerifier
.setConnectionManager(connectionManager)
因此,应该配置连接管理器
Files.copy(ClassLoader.getSystemResourceAsStream("keystore"), Paths.get(URI.create("file:/tmp/keystore")),
StandardCopyOption.REPLACE_EXISTING);
Registry<ConnectionSocketFactory> socketFactoryRegistry =
RegistryBuilder
.<ConnectionSocketFactory>create()
.register(
"https",
new SSLConnectionSocketFactory(SSLContextBuilder.create()
.loadTrustMaterial(new File("/tmp/keystore")).build(),
new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
})).register("http", PlainConnectionSocketFactory.INSTANCE).build();
PoolingHttpClientConnectionManager connectionManager =
new PoolingHttpClientConnectionManager(socketFactoryRegistry);
CloseableHttpClient httpClient =
HttpClientBuilder.create()
.setConnectionManager(connectionManager)
.build();
Files.copy(ClassLoader.getsystemresourceastream(“keystore”)、path.get(URI.create(“file:/tmp/keystore”),
StandardCopyOption。替换_现有);
注册表socketFactoryRegistry=
注册表生成器
.create()
.登记(
“https”,
新的SSLConnectionSocketFactory(SSLContextBuilder.create())
.loadTrustMaterial(新文件(“/tmp/keystore”)).build(),
新主机名验证程序(){
@凌驾
公共布尔验证(字符串主机名、SSLSession会话){
返回true;
}
})).register(“http”,PlainConnectionSocketFactory.INSTANCE).build();
PoolighttpClientConnectionManager连接管理器=
新的PoollightTPClientConnectionManager(socketFactoryRegistry);
可关闭的httpClient httpClient=
HttpClientBuilder.create()
.setConnectionManager(connectionManager)
.build();
注
- -Djavax.net.debug=all debug选项对于查看正在使用的证书非常有用
- SSLContext使用File,如果我们计划将证书和代码打包到一个Jar中,那么我们需要创建一个文件将其传递给File对象(它不适用于Jar中的文件) Files.copy(ClassLoader.getsystemresourceastream(“keystore”)、path.get(URI.create(“file:/tmp/utskeystore”)、StandardCopyOption.REPLACE_EXISTING)
Files.copy(ClassLoader.getSystemResourceAsStream("keystore"), Paths.get(URI.create("file:/tmp/keystore")),
StandardCopyOption.REPLACE_EXISTING);
Registry<ConnectionSocketFactory> socketFactoryRegistry =
RegistryBuilder
.<ConnectionSocketFactory>create()
.register(
"https",
new SSLConnectionSocketFactory(SSLContextBuilder.create()
.loadTrustMaterial(new File("/tmp/keystore")).build(),
new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
})).register("http", PlainConnectionSocketFactory.INSTANCE).build();
PoolingHttpClientConnectionManager connectionManager =
new PoolingHttpClientConnectionManager(socketFactoryRegistry);
CloseableHttpClient httpClient =
HttpClientBuilder.create()
.setConnectionManager(connectionManager)
.build();