Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用java中的自定义信任库和默认信任库_Java_Ssl_Keystore_Truststore - Fatal编程技术网

使用java中的自定义信任库和默认信任库

使用java中的自定义信任库和默认信任库,java,ssl,keystore,truststore,Java,Ssl,Keystore,Truststore,我正在用Java编写一个应用程序,它通过HTTPS连接到两个web服务器。一个通过默认信任链获得信任的证书,另一个使用自签名证书。当然,连接到第一台服务器是开箱即用的,而使用自签名证书连接到服务器是不起作用的,直到我使用来自该服务器的证书创建了一个信任库。但是,到默认受信任服务器的连接不再起作用,因为显然,一旦我创建了自己的信任库,默认信任库就会被忽略 我找到的一个解决方案是将默认信任库中的证书添加到我自己的信任库中。然而,我不喜欢这个解决方案,因为它需要我继续管理这个信任库。(我不能假设这些证

我正在用Java编写一个应用程序,它通过HTTPS连接到两个web服务器。一个通过默认信任链获得信任的证书,另一个使用自签名证书。当然,连接到第一台服务器是开箱即用的,而使用自签名证书连接到服务器是不起作用的,直到我使用来自该服务器的证书创建了一个信任库。但是,到默认受信任服务器的连接不再起作用,因为显然,一旦我创建了自己的信任库,默认信任库就会被忽略

我找到的一个解决方案是将默认信任库中的证书添加到我自己的信任库中。然而,我不喜欢这个解决方案,因为它需要我继续管理这个信任库。(我不能假设这些证书在可预见的未来保持不变,对吗?)

除此之外,我还发现两个5年前的线程存在类似问题:


他们都深入研究了JavaSSL基础设施。我希望现在有一个更方便的解决方案,我可以在代码的安全审查中轻松解释。

您可以使用类似于我在a中提到的模式(针对不同的问题)

本质上,掌握默认的信任管理器,创建第二个使用您自己的信任存储的信任管理器。将它们都包装在自定义的信任管理器实现中,委托调用这两个实现(当一个失败时返回另一个)

您不必将该上下文设置为默认上下文。如何使用它取决于所使用的客户端库(以及它从何处获得套接字工厂)


也就是说,原则上,无论如何,您都必须根据需要更新信任库。Java 7 JSSE参考指南对此有一个“重要注意事项”,现在降级为:

JDK附带的受信任根证书数量有限 javahome/lib/security/cacerts文件。如keytool中所述 参考页,您有责任维护(即添加 并删除)此文件中包含的证书(如果使用此 文件作为信任库

取决于您所访问的服务器的证书配置 联系,您可能需要添加其他根证书。获得 需要相应供应商提供的特定根证书


正如我所想,您还可以使用Apache HttpComponents库中的
SSLContextBuilder
类将自定义密钥库添加到
SSLContext

SSLContextBuilder builder = new SSLContextBuilder();
try {
     keyStore.load(null, null);
     builder.loadTrustMaterial(keyStore, null);
     builder.loadKeyMaterial(keyStore, null);
} catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException
          | UnrecoverableKeyException e) {
     log.error("Can not load keys from keystore '{}'", keyStore.getProvider(), e);
}
return builder.build();

您可以通过调用
TrustManagerFactory.init((KeyStore)null)
检索默认信任存储,并获取其
X509Certificate
s。将此与您自己的证书相结合。您可以从带有
密钥库的
.jks
.p12
文件加载自签名证书。加载
,也可以通过
证书库
加载
.crt
(或
.cer
)文件

下面是一些演示代码,说明了这一点。如果使用浏览器从stackoverflow.com下载证书,则可以运行代码。如果您注释掉添加加载的证书和默认证书,代码将获得一个
SSLHandshakeException
,但如果保留其中一个,它将返回状态代码200

导入javax.net.ssl.*;
导入java.io.*;
导入java.net.URL;
导入java.security.*;
导入java.security.cert.*;
公共类HttpsWithCustomCertificateDemo{
公共静态void main(字符串[]args)引发异常{
//创建一个新的信任存储,对.jks文件使用getDefaultType,对.p12文件使用“pkcs12”
KeyStore trustStore=KeyStore.getInstance(KeyStore.getDefaultType());
//创建一个新的信任存储,对.jks文件使用getDefaultType,对.p12文件使用“pkcs12”
load(null,null);
//如果您注释掉以下内容,请求将失败
trustStore.setCertificateEntry(
“堆栈溢出”,
//要进行测试,请使用浏览器从stackoverflow.com下载证书
loadCertificate(新文件(“stackoverflow.crt”))
);
//取消对以下内容的注释,将已安装的证书也添加到密钥库中
//addDefaultRootCaCertificates(信任库);
SSLSocketFactory SSLSocketFactory=创建SSLSocketFactory(信任库);
URL=新URL(“https://stackoverflow.com/");
HttpsURLConnection conn=(HttpsURLConnection)url.openConnection();
//或者,要对所有Http请求使用sslSocketFactory,请取消注释
//HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);
连接设置插座工厂(sslSocketFactory);
System.out.println(conn.getResponseCode());
}
私有静态SSLSocketFactory CreateSLSocketFactory(密钥库信任库)引发GeneralSecurityException{
TrustManagerFactory tmf=TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(信任库);
TrustManager[]TrustManager=tmf.getTrustManager();
SSLContext SSLContext=SSLContext.getInstance(“SSL”);
init(null,trustManagers,null);
返回sslContext.getSocketFactory();
}
私有静态X509CertificateLoadCertificate(文件certificateFile)引发IOException、CertificateException{
try(FileInputStream-inputStream=newfileinputstream(certificateFile)){
返回(X509Certificate)CertificateFactory.getInstance(“X509”).generateCertificate(inputStream);
}
}
私有静态void addDefaultRootCaCertificates(密钥库信任库)引发GeneralSecurityException{
TrustManagerFactory TrustManagerFactory=TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
//加载默认根CA证书(通常从JAVA_HOME/lib/cacerts)
trustManagerFactory.ini
SSLContextBuilder builder = new SSLContextBuilder();
try {
     keyStore.load(null, null);
     builder.loadTrustMaterial(keyStore, null);
     builder.loadKeyMaterial(keyStore, null);
} catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException
          | UnrecoverableKeyException e) {
     log.error("Can not load keys from keystore '{}'", keyStore.getProvider(), e);
}
return builder.build();