Выбор SSL-сертификата клиента в Java

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

Сделать приложение использовать сертификат для вызова очень просто; настройка javax.net.ssl.keyStore и javax.net.ssl.keyStorePassword сделает это. Однако проблема заключается в том, как сделать так, чтобы он использовал только сертификат при вызове этой конкретной веб-службы. Я предполагаю, что в более общем плане мы хотели бы иметь возможность выбрать сертификат клиента, который будет использоваться, если таковой имеется.

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

Предполагается, что каждый клиент службы полностью независим друг от друга, и они индивидуально упаковываются в отдельные JAR. Таким образом, один из вариантов, который произошел со мной (хотя мы не проанализировали его должным образом) заключается в том, чтобы каким-то образом изолировать каждый JAR, возможно, загружать каждый из них под другую виртуальную машину с разными параметрами. Это просто идея, что я не знаю, как ее реализовать (или, если возможно, даже если это возможно).

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

Мы используем classы Java 1.5, Axis2 и клиента, созданные с помощью wsimport или wsdl2java .

Java-клиенты SSL будут отправлять сертификат только по запросу сервера. Сервер может отправить необязательный намек о том, какие сертификаты он примет; это поможет клиенту выбрать один сертификат, если он имеет несколько.

Обычно создается новый SSLContext с определенным сертификатом клиента, а экземпляры Socket создаются с фабрики, полученной из этого контекста. К сожалению, Axis2, похоже, не поддерживает использование SSLContext или пользовательского SocketFactory . Его настройки сертификата клиента являются глобальными.

Конфигурация выполняется через SSLContext , который фактически является фабрикой для SSLSocketFactory (или SSLEngine ). По умолчанию это будет настроено из свойств javax.net.ssl.* . Кроме того, когда сервер запрашивает сертификат, он отправляет сообщение TLS / SSL CertificateRequest которое содержит список отличительных имен CA, которые он готов принять. Хотя этот список строго говоря только ориентировочный (т.е. серверы могут принимать сертификаты от эмитентов, не входящих в список, или могут отказаться от действительных сертификатов из ЦС в списке), он обычно работает таким образом.

По умолчанию выбор сертификата в X509KeyManager настроенном в SSLContext (опять вам не нужно беспокоиться об этом), выберет один из сертификатов, который был выпущен одним из них (или может быть привязан к эмитенту там). Этот список является параметром issuers в X509KeyManager.chooseClientAlias ( alias – это псевдоним для сертификата, который вы хотите выбрать, как указано в хранилище ключей). Если у вас несколько кандидатов, вы также можете использовать параметр socket , который даст вам IP-адрес партнера, если это поможет сделать выбор.

Если это поможет, вы можете найти jSSLutils (и его оболочку) для конфигурации вашего SSLContext (это главным образом вспомогательные classы для сборки SSLContext s). (Обратите внимание, что этот пример предназначен для выбора псевдонима на стороне сервера, но его можно адаптировать, исходный код доступен .)

После этого вы должны найти документацию относительно системного свойства axis.socketSecureFactory в Axis (и SecureSocketFactory ). Если вы посмотрите на исходный код Axis, не должно быть слишком сложно создать org.apache.axis.components.net.SunJSSESocketFactory который инициализирован из SSLContext по вашему выбору (см. Этот вопрос ).

Просто понял, что вы говорили о Axis2, где SecureSocketFactory похоже, исчез. Возможно, вам удастся найти обходной путь с использованием SSLC по умолчанию, но это повлияет на все ваше приложение (что не очень удобно). Если вы используете X509KeyManagerWrapper jSSLutils, вы можете использовать X509KeyManager по умолчанию и рассматривать только определенные хосты в качестве исключения. (Это не идеальная ситуация, я не уверен, как использовать пользовательский SSLContext / SSLSocketFactory в Axis 2.)

В качестве альтернативы, согласно этому документу Axis 2 , похоже, что Axis 2 использует Apache HTTP Client 3.x:

Если вы хотите выполнить аутентификацию SSL-клиента (двухсторонний SSL), вы можете использовать функцию Protocol.registerProtocol для HttpClient. Вы можете перезаписать протокол «https» или использовать другой протокол для вашей проверки подлинности SSL-клиента, если вы не хотите связываться с обычным https. Дополнительную информацию можно найти на странице http://jakarta.apache.org/commons/httpclient/sslguide.html.

В этом случае SslContextedSecureProtocolSocketFactory должен помочь вам настроить SSLContext .

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

 /** * This method does the following: * 1. Creates a new and unique protocol for each SSL URL that is secured by client certificate * 2. Bind keyStore related information to this protocol * 3. Registers it with HTTP Protocol object * 4. Stores the local reference for this custom protocol for use during furture collect calls * * @throws Exception */ public void registerProtocolCertificate() throws Exception { EasySSLProtocolSocketFactory easySSLPSFactory = new EasySSLProtocolSocketFactory(); easySSLPSFactory.setKeyMaterial(createKeyMaterial()); myProtocolPrefix = (HTTPS_PROTOCOL + uniqueCounter.incrementAndGet()); Protocol httpsProtocol = new Protocol(myProtocolPrefix,(ProtocolSocketFactory) easySSLPSFactory, port); Protocol.registerProtocol(myProtocolPrefix, httpsProtocol); log.trace("Protocol [ "+myProtocolPrefix+" ] registered for the first time"); } /** * Load keystore for CLIENT-CERT protected endpoints */ private KeyMaterial createKeyMaterial() throws GeneralSecurityException, Exception { KeyMaterial km = null; char[] password = keyStorePassphrase.toCharArray(); File f = new File(keyStoreLocation); if (f.exists()) { try { km = new KeyMaterial(keyStoreLocation, password); log.trace("Keystore location is: " + keyStoreLocation + ""); } catch (GeneralSecurityException gse) { if (logErrors){ log.error("Exception occured while loading keystore from the following location: "+keyStoreLocation, gse); throw gse; } } } else { log.error("Unable to load Keystore from the following location: " + keyStoreLocation ); throw new CollectorInitException("Unable to load Keystore from the following location: " + keyStoreLocation); } return km; } 

Когда мне приходится ссылаться на веб-службу, я делаю это (которые в основном заменяют «https» в URL с помощью https1 или https2 или что-то еще в зависимости от протокола, который вы инициализировали для этой конкретной конечной точки):

 httpClient.getHostConfiguration().setHost(host, port,Protocol.getProtocol(myProtocolPrefix)); initializeHttpMethod(this.url.toString().replace(HTTPS_PROTOCOL, myProtocolPrefix)); 

Отлично работает!

  • Возврат сервиса WCF «Метод не разрешен»
  • В чем разница между XML-RPC и SOAP?
  • jqgrid добавить строку и отправить данные в webservice для вставки
  • Установка HttpContext.Current.Session в модульном тесте
  • Тестирование веб-сервисов REST
  • asp.net asmx веб-сервис возвращает xml вместо json
  • Каковы различия между веб-службами WCF и ASMX?
  • JQuery Ajax Проводка json для webservice
  • Лучший способ вызова JSON WebService из .NET Console
  • Почему статические методы не используются в качестве веб-служб в веб-службах ASMX?
  • Ошибка 415 Неподдерживаемый тип носителя: POST не достигает REST, если JSON, но это происходит, если XML
  • Давайте будем гением компьютера.