我正在添加到我们的大型Java应用程序的模块必须与另一家公司的SSL安全网站进行交谈.问题是该站点使用自签名证书.我有一份证书副本,以验证我没有遇到中间人攻击,我需要将此证书合并到我们的代码中,以便与服务器的连接成功.
这是基本代码:
void sendRequest(String dataPacket) {
String urlStr = "https://host.example.com/";
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setMethod("POST");
conn.setRequestProperty("Content-Length", data.length());
conn.setDoOutput(true);
OutputStreamWriter o = new OutputStreamWriter(conn.getOutputStream());
o.write(data);
o.flush();
}
Run Code Online (Sandbox Code Playgroud)
在没有为自签名证书进行任何额外处理的情况下,这会在conn.getOutputStream()处死,但有以下异常:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
....
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
....
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path …Run Code Online (Sandbox Code Playgroud) 我正在用Java编写一个应用程序,它通过HTTPS连接到两个Web服务器.一个通过默认的信任链获得证书,另一个使用自签名证书.当然,连接到第一台服务器是开箱即用的,而在我使用该服务器的证书创建一个trustStore之前,使用自签名证书连接到服务器不起作用.但是,与默认可信服务器的连接不再起作用,因为显然我创建自己的默认trustStore会被忽略.
我找到的一个解决方案是将证书从默认的trustStore添加到我自己的.但是,我不喜欢这个解决方案,因为它需要我继续管理那个trustStore.(我不能假设这些证书在可预见的未来仍然是静态的,对吧?)
除此之外,我发现了两个有着类似问题的5岁线程:
他们都深入到Java SSL基础架构.我希望到现在有一个更方便的解决方案,我可以在我的代码的安全审查中轻松解释.
我正在为内部客户端分发库jar,并且该库包含一个证书,用于调用也是我们网络内部的服务.
信任管理器的设置如下
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore keystore = KeyStore.getInstance("JKS");
InputStream keystoreStream =
clazz.getClassLoader().getResourceAsStream("certs.keystore"); // (on classpath)
keystore.load(keystoreStream, "pa55w0rd".toCharArray());
trustManagerFactory.init(keystore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
SSLContext context = SSLContext.getInstance("SSL");
context.init(null, trustManagers, null);
SSLSocketFactory socketFact = context.getSocketFactory();
connection.setSSLSocketFactory(socketFact);
Run Code Online (Sandbox Code Playgroud)
所有这些都可以正常工作,除非用户需要其他证书或默认证书.
我试过这个 在JVM中注册多个密钥库而没有运气(我在为我的情况推广它时遇到了麻烦)
我如何使用我的证书并仍允许用户库使用自己的证书?
我的应用程序有一个个人密钥库,其中包含用于本地网络的可信自签名证书 - 比如说mykeystore.jks.我希望能够使用已在本地配置的自签名证书连接到公共站点(例如google.com)以及本地网络中的站点.
这里的问题是,当我连接到https://google.com时,路径构建失败,因为设置我自己的密钥库会覆盖包含与JRE捆绑在一起的根CA的默认密钥库,报告异常
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Run Code Online (Sandbox Code Playgroud)
但是,如果我将CA证书导入我自己的密钥库(mykeystore.jks),它可以正常工作.有没有办法支持两者?
我有自己的TrustManger用于此目的,
public class CustomX509TrustManager implements X509TrustManager {
X509TrustManager defaultTrustManager;
public MyX509TrustManager(KeyStore keystore) {
TrustManagerFactory trustMgrFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustMgrFactory.init(keystore);
TrustManager trustManagers[] = trustMgrFactory.getTrustManagers();
for (int i = 0; i < trustManagers.length; i++) {
if (trustManagers[i] instanceof X509TrustManager) {
defaultTrustManager = (X509TrustManager) trustManagers[i];
return;
}
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
try …Run Code Online (Sandbox Code Playgroud) 我有一个在weblogic服务器上运行的Java应用程序.该应用程序有两个不同的模块,使用SSL连接到外部Web服务 - 比如模块A和模块B.
模块A - 基于Axis构建 - 使用信任库A Moudle B - 基于Spring-ws构建 - 使用信任库B.
模块A存在.正在介绍模块B.
我需要能够根据调用的模块在JVM中动态设置信任库.
由于某些限制,我没有选项 - 创建自定义密钥管理器. - 使用一个信任库
我尝试使用System.setProperty im Module B codebase来设置truststore.但是,仅当模块B首先被调用时才有效.例如 - 假设我重新启动JVM然后调用模块A - 它在JVM中设置它自己的信任库然后我调用模块B - 它失败 - 它没有在JVM中设置它自己的信任库,即使我已经使用过System.setProperty方法.
我错过了什么,或者只是System.setProperty不会覆盖现有的设置值.如果是这样,我的选择是什么.