java - Java缓存SSL失败 - 我可以以某种方式刷新这些
问题描述
我正在尝试在单元测试中测试我的 SSL 实现,并且有一个我不太理解的场景。
当我连接到主机一次并失败时,即使它具有正确的证书,随后的每个连接也会失败。我假设在某个地方我必须刷新缓存。
这是我的代码,服务器和客户端在本地运行。我将一个 jks-File 用于 trustStore 和 keyStore。无论最初的错误是什么,都会发生错误,下次我总是会遇到第一个错误。
如果我不执行第一个请求,则第二个请求有效。
如果您想知道这里的用例是什么,我们有一些本地服务器使用来自内部 PKI 的 https 证书,当有人错误配置服务器或证书时,我们希望能够明显地更改它们,而无需关闭整个虚拟机。
//attempt a connection without certificates, will fail
try (final InputStream stream = new URL("https://localhost:" + port).openStream()){
System.out.println(IOUtils.toString(stream, Charset.defaultCharset()));
} catch (IOException e){
System.out.println("Failed to load: " + StackTraceUtil.getStackTrace(e));
}
//copies the jks file to a temporary location
final File jksFile = copyJKSFile();
//ignore host names, running locally, won't use this in production
HttpsURLConnection.setDefaultHostnameVerifier((hostname, sslSession) -> hostname.equalsIgnoreCase("localhost"));
//set the system properties
System.setProperty("javax.net.ssl.keyStore", jksFile.getAbsolutePath());
System.setProperty("javax.net.ssl.keyStorePassword", password);
System.setProperty("javax.net.ssl.trustStore", jksFile.getAbsolutePath());
System.setProperty("javax.net.ssl.trustStorePassword", password);
//this should work now
try (final InputStream stream = new URL("https://localhost:" + port).openStream()){
System.out.println(IOUtils.toString(stream, Charset.defaultCharset()));
} catch (IOException e){
System.out.println("Failed to load: " + StackTraceUtil.getStackTrace(e));
}
谢谢你的帮助!
解决方案
所以我找到了一个解决方案,我想我会分享它,以防其他人在某个时候遇到这个问题。
该类javax.net.ssl.HttpsURLConnection
使用 ajavax.net.ssl.SSLSocketFactory
来加载 Key- 和 TrustStore,后者在javax.net.ssl.SSLContext
内部使用 a。当您不覆盖任何内容时,它会使用默认实现,该实现会加载文件并且一旦加载就无法重置。
所以我所做的不是使用默认实现,而是设置我自己的SSLContext
,当我知道文件会改变时。
final SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
如果你想使用旧版本的 TLS,完整列表应该在这里
推荐阅读
- python - 如何根据值更改 Python 类/对象的一个或多个属性
- css - 如何在 CSS 中使用背景图像制作悬停循环
- python - 正确的循环头根据输入到函数中的参数进入循环
- powershell - powershell cmdlet 如何将信息或错误通过管道传输到 write-eventlog
- java - 在 xdocreport 中使用模板填充表
- sql - 从一列 SQL postgres 中的时间戳计算持续时间
- java - 控制器返回列表时如何从jquery每个循环中获取值
- arduino - 将char数组解析为整数,atoi()返回平方
- spring - 如何在 SpringBoot 中使用 SimpleUrlHandlerMapping
- javascript - 动态表并保持头部固定