Java中HTTPS会遇到的问题
访问自签名的HTTPS网站
高版本JRE访问SSLv3/SSLv2站点
一些银行接口需要加载keystore的场景
* 如果要了解SSL历史也可以看看这篇文章。
1 访问自签名的HTTPS网站
常常看到的回答是直接通过信任所有来支持, 这不优雅; 优雅的操作应该:
下载服务端的CA证书
# 方式1: 导出DER格式的证书
# 这里需要通过指定servername来保证导出的证书和当前域名匹配
openssl s_client -showcerts -connect self-signed.badssl.com:443 -servername self-signed.badssl.com /dev/null|openssl x509 -outform der >self-signed.badssl.com.der
代码中通过加载服务端证书后通过自定义SSLContext访问目标服务器:
private SSLContext sslContext(File certificateFile, String certificateType) {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(certificateFile);
CertificateFactory cf = CertificateFactory.getInstance(certificateType);
Certificate certificate = cf.generateCertificate(inputStream);
System.out.println("ca=" + ((X509Certificate) certificate).getSubjectDN());
String alias = ((X509Certificate) certificate).getSubjectDN().toString();
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry(alias, certificate);
// Create a KeyStore containing our trusted CAs
SSLContext sslcontext = SSLContexts.custom()
.loadTrustMaterial(keyStore, new TrustSelfSignedStrategy())
.build();
return sslcontext;
} catch (IOException e) {
throw new RuntimeException(e);
} catch (CertificateException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (KeyStoreException e) {
throw new RuntimeException(e);
} catch (KeyManagementException e) {
throw new RuntimeException(e);
} finally {
if (inputStream != null) try { inputStream.close(); } catch (IOException e) { }
}
}
@Test
public void testSelfSign() throws IOException {
File certFile = ResourceUtils.getFile(this.getClass().getResource("/root.cer"));
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLContext(sslContext(certFile, "X.5