简体   繁体   English

我的带有内置ssl证书的库如何允许使用默认证书

[英]How can my library with built in ssl certificate also allow use with default certs

I am distributing a library jar for internal clients, and the library includes a certificate which it uses to call a service that is also internal to our network. 我正在为内部客户端分发库jar,并且该库包含一个证书,用于调用也是我们网络内部的服务。

The trust manager is set up as follows 信任管理器的设置如下

    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);

All of this works fine except in cases where users need other certificates or the default certificate. 所有这些都可以正常工作,除非用户需要其他证书或默认证书。

I tried this Registering multiple keystores in JVM with no luck (I am having trouble generalizing it for my case) 我试过这个在JVM中注册多个密钥库而没有运气(我在为我的情况推广它时遇到了麻烦)

How can I use my cert and still allow user libraries to use their own certs as well? 我如何使用我的证书并仍允许用户库使用自己的证书?

You are configuring a connection with a custom keystore acting as a truststore ( a certificate of your server that you trust). 您正在配置与充当信任库的自定义密钥库的连接(您信任的服务器的证书)。 You are not overriding the default JVM behaviour, so the rest of the connection that other applications that include your library can make will not be affected. 您没有覆盖默认的JVM行为,因此包含您的库的其他应用程序可以创建的其余连接不会受到影响。

Therefore you do not need a multiple keystore manager, in fact, your code works perfectly. 因此,您不需要多个密钥库管理器,事实上,您的代码完美无缺。

I've attached a full example below using a keystore google.jks which includes Google's root CA, and a connection using the default JVM truststore. 我在下面使用密钥库google.jks附加了一个完整的示例,其中包括Google的根CA和使用默认JVM信任库的连接。 This is the output 这是输出

request("https://www.google.com/", "test/google.jks", "pa55w0rd"); //OK 
request("https://www.aragon.es/", "test/google.jks", "pa55w0rd");  // FAIL sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
request("https://www.aragon.es/", null, null); //OK

The problem is not in the code you have attached, so check the following in your code: 问题不在您附加的代码中,因此请在代码中检查以下内容:

  • The truststore certs.keystore is really found in your classpath 您可以在类路径中找到truststore certs.keystore

  • Truststore settings are not set at JVM level using -Djavax.net.ssl.trustStore 使用-Djavax.net.ssl.trustStore未在JVM级别设置Truststore设置

  • The errors found (please include it in your question) are really related to the SSL connection 发现的错误(请将其包含在您的问题中)与SSL连接真正相关


package test;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyStore;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;


public class HTTPSCustomTruststore {

    public final static void main (String argv[]) throws Exception{
        request("https://www.google.com/", "test/google.jks", "pa55w0rd"); //Expected OK 
        request("https://www.aragon.es/","test/google.jks","pa55w0rd");  // Expected  FAIL
        request("https://www.aragon.es/",null,null); //using default truststore. OK 
    }

    public static void configureCustom(HttpsURLConnection connection, String truststore, String pwd)throws Exception{
        TrustManagerFactory trustManagerFactory = 
                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        KeyStore keystore = KeyStore.getInstance("JKS");
        InputStream keystoreStream = HTTPSCustomTruststore.class.getClassLoader().getResourceAsStream(truststore);
        keystore.load(keystoreStream, pwd.toCharArray());
        trustManagerFactory.init(keystore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        SSLContext context = SSLContext.getInstance("SSL");
        context.init(null, trustManagers,  new java.security.SecureRandom());

        SSLSocketFactory socketFact = context.getSocketFactory();
        connection.setSSLSocketFactory(socketFact);
    }


    public static void request(String urlS, String truststore, String pwd) {
        try {
            URL url = new URL(urlS);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            if (truststore != null) {
                configureCustom((HttpsURLConnection) conn, truststore, pwd);
            }   
            conn.connect();

            int statusCode = conn.getResponseCode();
            if (statusCode != 200) {
                System.out.println(urlS + " FAIL");
            } else {
                System.out.println(urlS + " OK");
            }
        } catch (Exception e) {
            System.out.println(urlS + " FAIL " + e.getMessage());
        }
    }
}

您可以将默认证书导入自定义商店以具有组合的自定义商店并使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Wildfly-允许无需证书即可连接到SSL站点 - Wildfly - Allow connections to SSL sites without certs 在SSL握手期间,Java客户端如何使用本机Windows-MY存储来提供其客户端证书? - How can a Java client use the native Windows-MY store to provide its client certificate as required during a SSL handshake? 如果keytool.exe无法从我的证书建立证书链,该怎么办? - What do I do when keytool.exe can't establish a certificate chain from my certs? Android如何允许来自特定服务器的特定SSL证书 - Android How to allow specific SSL certificate from a specific server 如何为嵌入式证书指定JVM SSL参数? - How to specify JVM SSL arguments for embedded certs? 如何为tomcat密钥库安装SSL证书 - How to install SSL Certs for tomcat keystore 如何在Android中使用自签名SSL证书 - How to use a self signed SSL certificate in Android SSL客户端如何接受过期的SSL证书 - How can a ssl client accept an expired SSL certificate 如何设置 letencrypt SSL 证书并在 Spring Boot 应用程序中使用它? - How can I set up a letsencrypt SSL certificate and use it in a Spring Boot application? 可以将Jetty配置为提供AWS Certificate Manager证书吗? - Can Jetty be configured to serve AWS Certificate Manager certs?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM