当前位置: 首页 > 知识库问答 >
问题:

在Java中使用自定义信任库和默认信任库

毋胜涝
2023-03-14

我正在Java写一个应用程序,它通过HTTPS连接到两个web服务器。其中一个通过默认信任链获得信任证书,另一个使用自签名证书。当然,连接到第一个服务器是开箱即用的,而使用自签名证书连接到服务器则是不起作用的,直到我使用该服务器的证书创建了信任存储区。然而,到默认受信任服务器的连接不再起作用,因为显然,在创建了自己的信任存储区之后,默认信任存储区将被忽略。

我发现的一个解决方案是将默认信任库中的证书添加到我自己的信任库中。但是,我不喜欢这个解决方案,因为它要求我不断管理那个信任库。(我不能假设这些证书在可预见的未来保持静止,对吧?)

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

在JVM中注册多个密钥库

如何为一台Java服务器拥有多个SSL证书

它们都深入到Java SSL基础设施中。我希望现在有一个更方便的解决方案,我可以在对代码进行安全检查时轻松地解释。

共有1个答案

刘弘济
2023-03-14

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

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

TrustManagerFactory tmf = TrustManagerFactory
    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
// Using null here initialises the TMF with the default trust store.
tmf.init((KeyStore) null);

// Get hold of the default trust manager
X509TrustManager defaultTm = null;
for (TrustManager tm : tmf.getTrustManagers()) {
    if (tm instanceof X509TrustManager) {
        defaultTm = (X509TrustManager) tm;
        break;
    }
}

FileInputStream myKeys = new FileInputStream("truststore.jks");

// Do the same with your trust store this time
// Adapt how you load the keystore to your needs
KeyStore myTrustStore = KeyStore.getInstance(KeyStore.getDefaultType());
myTrustStore.load(myKeys, "password".toCharArray());

myKeys.close();

tmf = TrustManagerFactory
    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(myTrustStore);

// Get hold of the default trust manager
X509TrustManager myTm = null;
for (TrustManager tm : tmf.getTrustManagers()) {
    if (tm instanceof X509TrustManager) {
        myTm = (X509TrustManager) tm;
        break;
    }
}

// Wrap it in your own class.
final X509TrustManager finalDefaultTm = defaultTm;
final X509TrustManager finalMyTm = myTm;
X509TrustManager customTm = new X509TrustManager() {
    @Override
    public X509Certificate[] getAcceptedIssuers() {
        // If you're planning to use client-cert auth,
        // merge results from "defaultTm" and "myTm".
        return finalDefaultTm.getAcceptedIssuers();
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain,
            String authType) throws CertificateException {
        try {
            finalMyTm.checkServerTrusted(chain, authType);
        } catch (CertificateException e) {
            // This will throw another CertificateException if this fails too.
            finalDefaultTm.checkServerTrusted(chain, authType);
        }
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain,
            String authType) throws CertificateException {
        // If you're planning to use client-cert auth,
        // do the same as checking the server.
        finalDefaultTm.checkClientTrusted(chain, authType);
    }
};


SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { customTm }, null);

// You don't have to set this as the default context,
// it depends on the library you're using.
SSLContext.setDefault(sslContext);

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

话虽如此,但原则上,无论如何,您都必须根据需要更新信任库。《Java 7JSSE参考指南》对此有一个“重要注释”,现在在该指南的第8版中降级为一个“注释”:

JDK在Java-home/lib/security/cacerts文件中附带了数量有限的受信任根证书。如keytool参考页面中所述,如果您将该文件用作信任库,则您有责任维护(即添加和删除)该文件中包含的证书。

根据您联系的服务器的证书配置,您可能需要添加其他根证书。从相应的供应商获取所需的特定根证书。

 类似资料:
  • 我目前正在使用Weblogic 12c(12.1.1.0)。我有一个特殊的问题,我无法解决它。我已将服务器配置为使用自定义密钥存储和信任存储。我用的是-Djavax。网调试=用于调试的ssl。当服务器启动时,部署的应用程序使用https连接到另一个应用程序进行验证。在此连接过程中,使用自定义信任存储验证其证书。 验证按预期完成,然后服务器启动而不报告任何错误。现在,一旦我访问IE上的应用程序并执行

  • 问题内容: 我有一个正在Tomcat 7(Windows)上运行的Java servlet,它连接 到SQL Server数据库。现在,我需要加密此连接,并且 在密钥库中有一个公共密钥SSL证书。但是显然我必须 为“信任库”配置系统属性,并将信任 库设置为密钥库。 密钥库的位置是C:\ SSLKeys \ appkeystore.key,根据我发现的内容 ,必须使用以下命令设置信任库; 但是我该如

  • 问题内容: 我正在编写使用SSL的应用程序。因此,我有一个虚拟密钥库和一个虚拟信任库,我想提供给我的客户。是否有任何默认文件夹可将它们放入我的发行版中?例如docs,lib,bin …等。密钥库通常放在服务器上的什么地方,信任库通常放在客户端的什么地方? 谢谢 问题答案: 在Java中,根据JSSE参考指南,没有默认值,默认值为“ jssecacerts(如果存在),否则为cacerts ”。 一

  • 我已经创建了一个Weblogic 12c域,其中包含一个托管服务器,并在该服务器上安装了SOA Suite 12.2。为了能够在我的组合中通过SSL调用REST服务,我创建了一个带有有效证书链的信任库,以便通过SSL连接到REST服务器。 我使用/u01/data/keystores/identitykeystore中的自定义标识存储为SOA托管服务器创建了自定义标识和自定义信任。jks和信任存储

  • 我正在编写一个Java 8应用程序,希望使用自签名证书建立一个简单的密钥库和信任库。 通常情况如下: 使用创建密钥对证书。 使用创建. jks密钥库. jks信任库 现在我只想使用并创建。p12密钥库而不是。jks密钥库。 创建一个。p12密钥库使用以下命令非常有效: 这个密钥库似乎工作正常,因为在我的Java应用程序中提供相应的. jks信任库将使TLS连接正常运行。但是我无法让. p12信任库

  • 我只使用自签名证书进行测试。 问题: Q1.我想知道为什么我需要在步骤6中将服务器和客户端自己的证书添加到各自的信任库中。 2.创建x509证书 openssl req-x509-new-nodes-key diagserverca.key-sha256-days 1024-out diagserverca.pem 3.从私钥和公共证书创建PKCS12密钥存储库。 keytool-importke