Через несколько клиентских сертификатов SSL в Java с одного узла

в моем Java-приложении мне нужно подключиться к одному хосту с помощью SSL, но каждый раз использовать другой сертификат. Причина, по которой мне нужно использовать разные сертификаты, заключается в том, что удаленный сайт использует свойство User ID, встроенное в сертификат для идентификации клиента.

это серверное приложение, которое работает на 3 разных операционных системах, и мне нужно иметь возможность переключать сертификаты без перезапуска процесса.

другой пользователь предложил импорт нескольких сертификатов в одно хранилище ключей. Я не уверен, что это помогает мне, хотя, если нет способа сказать Java, какой сертификат в хранилище ключей использовать.

2 ответов


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

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

инициализируйте контексты, которые вам понадобятся один раз, и повторно используйте правильный для каждого соединения. Если вы делаете несколько подключений, это позволит вам воспользоваться преимуществами сеансов SSL.

KeyManagerFactory kmf = 
  KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(identityStore, password);
TrustManagerFactory tmf =
  TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

позже, вы можете создать сокет напрямую:

SSLSocketFactory factory = ctx.getSocketFactory();
Socket socket = factory.createSocket(host, port);

или, если вы используете URL класс, вы можете указать SSLSocketFactory использовать при выполнении HTTPS-запросов:

HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setSSLSocketFactory(ctx.getSocketFactory());

Java 6 имеет дополнительный API, который упрощает настройку сокетов в соответствии с вашими предпочтениями для наборов шифров и т. д.


выход есть здесь для динамического выбора сертификата клиента, используемого для аутентификации SSL от клиента Axis.