Как моя библиотека со встроенным ssl-сертификатом также позволяет использовать сертификаты по умолчанию - PullRequest
0 голосов
/ 16 мая 2018

Я распространяю 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);

Все это прекрасно работает, за исключением случаев, когда пользователям нужны другие сертификаты или сертификат по умолчанию.

Я пробовал это Регистрация нескольких хранилищ ключей в JVM без удачи (у меня возникают проблемы при обобщении его для моего случая)

Как я могу использовать свой сертификат и при этом разрешить пользовательским библиотекам использовать также свои собственные сертификаты?

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Вы можете импортировать сертификаты по умолчанию в ваш пользовательский магазин, чтобы создать комбинированный пользовательский магазин и использовать его.

0 голосов
/ 24 мая 2018

Вы настраиваете соединение с пользовательским хранилищем ключей, действующим как хранилище доверенных сертификатов (сертификат вашего сервера, которому вы доверяете). Вы не переопределяете поведение JVM по умолчанию, поэтому это не повлияет на остальные соединения, которые могут устанавливать другие приложения, включающие вашу библиотеку.

Следовательно, вам не нужен менеджер нескольких хранилищ ключей, на самом деле ваш код работает отлично.

Я приложил полный пример ниже, используя хранилище ключей google.jks, которое включает корневой CA Google, и соединение, использующее хранилище доверенных сертификатов JVM по умолчанию. Это вывод

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

Проблема не в коде, который вы прикрепили, поэтому проверьте следующее в вашем коде:

  • Склад доверенных сертификатов certs.keystore действительно найден в вашем пути к классам

  • Настройки хранилища доверенных сертификатов не установлены на уровне JVM с использованием -Djavax.net.ssl.trustStore

  • Найденные ошибки (пожалуйста, включите их в свой вопрос) действительно связаны с 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());
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...