有人可以告诉我如何在没有关于主机名和证书的任何验证的情况下使用HttpClient v4.1发出HTTPS请求。我已经阅读了很多问题和论坛,并尝试了很多不同的事情,最终以此结束:
SSLContext context = SSLContext.getInstance("SSL");
context.init(new KeyManager[] {}, new TrustManager[] {}, new SecureRandom());
SSLSocketFactory sf = new SSLSocketFactory(context, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
client.getConnectionManager().getSchemeRegistry().register(new Scheme("https", 443, sf));
...然后当我去提出请求时,我得到:
javax.net.ssl.SSLPeerUnverifiedException:peer not authenticated
我知道我要做的事情并不安全。
答案 0 :(得分:0)
这样做了。我所迷失的变种和版本都很多:
context.init(new KeyManager[] {}, new TrustManager[] {new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {return null; }
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1)throws CertificateException {}
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1)throws CertificateException {}
}}, new SecureRandom());
我再次提到它,这不安全,除非你知道自己在做什么,否则不要这样做。
答案 1 :(得分:0)
诀窍是“ .loadTrustMaterial(null,(chain,authType)-> true)”)的一部分,传入始终返回true的trustStrategy,然后您可以跳过本地证书主机名验证,并且在修改主机文件以应用域-IP映射时也将起作用。
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream keyStoreFile = new FileInputStream(CERT_PATH);
ks.load(keyStoreFile, CERT_PASSWORD.toCharArray());
SSLContext sslContext = SSLContexts
.custom()
.loadKeyMaterial(ks, CERT_PASSWORD.toCharArray())
.loadTrustMaterial(null, (chain, authType) -> true)
.build();
SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(sslContext);
Registry<ConnectionSocketFactory> registry = RegistryBuilder
.<ConnectionSocketFactory>create()
.register(REST.HTTPS.LABEL, sslConnectionFactory)
.register(REST.HTTP.LABEL, new PlainConnectionSocketFactory())
.build();
BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager(registry);
httpClient = HttpClients
.custom()
.setConnectionManager(connManager)
.setSSLSocketFactory(sslConnectionFactory)
.build();