Настройка Glassfish в качестве клиента веб-сервисов с использованием взаимного SSL - PullRequest
4 голосов
/ 07 июня 2011

Я пытаюсь запросить данные у веб-службы, которая требует, чтобы клиент представил сертификат клиента. Сервер использует SSL для всех соединений и использует самозаверяющий сертификат. Я дал Netbeans WSDL-файл службы, и он сгенерировал код клиента с wsimport.

У меня нет проблем, когда мой клиентский код написан в обычном приложении Java; Я установил в хранилище доверия файл cacerts, содержащий сертификат сервера, установил хранилище ключей как файл, предоставленный администратором сервера в формате JKS, содержащий 2 ключа - личный ключ клиента и открытый ключ сервера, создаю объект запроса. и отправьте запрос.

Проблема возникает, когда я перемещаю ее в корпоративную среду Java. Требования диктуют, что код должен быть Enterprise JavaBean внутри Enterprise Archive, запущенного на сервере приложений Glassfish. Похоже, что Glassfish имеет свои собственные настройки безопасности, которые переопределяют настройки JVM. Когда выполняется метод EJB, содержащий вызов веб-службы, согласование SSL завершается ошибкой: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target. Я не знаю, как настроить параметры безопасности Glassfish как настройки моей JVM, кто-нибудь может объяснить настройки безопасности Glassfish? Проведенное мной исследование показало, как настроить Glassfish в качестве веб-службы сервер , а не веб-службы клиент .

У меня есть файл сертификата .cer для сервера, который я добавил в свое хранилище доверенных сертификатов, используя keytool Java для добавления его в файл cacerts по умолчанию. Было бы лучше изменить файл cacerts с помощью InstallCert для включения самозаверяющего сертификата, следуя инструкциям на http://blog.johnryding.com/post/1548502059/acquire-an-ssl-certificate-for-your-java-programs-in-win?

У меня есть файл хранилища доверенных сертификатов, файл хранилища ключей, файл сертификата .cer и сертификат браузера .p12, которые хранятся в $ JAVA_HOME / jre / lib / security и $ JAVA_HOME / lib / security.

Я использую Netbeans 6.9.1 и Glassfish 3.1 Final. Соответствующий фрагмент кода ниже, скопированный из моего EJB. Исключение возникает в последней строке.

System.setProperty("javax.net.ssl.trustStore", "C:\\jssecacerts"); System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); System.setProperty("javax.net.ssl.keyStore", "C:\\userCertificate.jks"); System.setProperty("javax.net.ssl.keyStorePassword", "password");<br> RequestObject request = new RequestObject;<br> request.setQuery("some data");<br> request.setUsername("user");<br> request.setPassword("pass");<br> Service service = new Service();<br> Endpoint port = service.getWebServicePort();<br> Result result = port.specificWebServiceMethod(request);

Ответы [ 4 ]

5 голосов
/ 25 июня 2012

Я столкнулся с тем же исключением, что и Жак Причард, описанный выше:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

I решено импортирование корневого сертификата в cacerts.jks и keystore.jks, используя следующие команды:

/usr/java/jdk1.6.0_25/bin/keytool -import -trustcacerts -file root_ca.cer -alias rootca -keystore cacerts.jks

/usr/java/jdk1.6.0_25/bin/keytool -import -trustcacerts -file root_ca.cer -alias rootca -keystore keystore.jks

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

1 голос
/ 13 июля 2011

У меня была именно эта проблема (с Glassfish 3.0.1).

Вот точные шаги, которые мы предприняли для решения этой проблемы.

    • a.Используйте команду Java Keytool, чтобы просмотреть хранилище ключей, чтобы увидеть, что в нем.Это полезно позже, чтобы увидеть, есть ли какие-либо изменения.Команда выглядит примерно так:

      keytool -list -keystore MyKeyStore.jks   
      
    • b.Преобразуйте pfx в pem, используя openssl.Обратите внимание, что я использовал правильный пароль для ввода pfx и тот же пароль, что и мое хранилище ключей Java для вывода файла pem.

      openssl pkcs12 -in MyPfxFile.pfx -out MyPemFile.pem
      
  1. Преобразование файла pemна p12, который может быть легко импортирован в хранилище ключей Java.Обратите внимание, что я использовал тот же пароль из моего хранилища ключей java, что и для входных и выходных файлов.

    openssl pkcs12 -export -in MyPemFile.pem -out MyP12File.p12
    
  2. Теперь я наконец импортирую p12 в свое хранилище ключей java.Обратите внимание, что я использовал java 6, в keytool для java 5 нет поддержки аргумента -importkeystore.

    keytool -importkeystore -deststorepass MyPassword -destkeystore PathToMyKeystore/keystore.jks -srckeystore MyP12File.p12 -srcstoretype PKCS12 -srcstorepass MyPassword
    
  3. Вы можете перечислить содержимое хранилища ключей здесь, например, как этот keytool -list-keystore keystore.jks просто для того, чтобы убедиться, что ваш новый ключ был импортирован правильно.

Если вам повезет, как я, вы обнаружите, что запуск вашего сервера приложений на этом этапе будетбыть бесполезным.Вы увидите ошибки, например что-то о пути pkix или что-то о HTTP 403 Forbidden.

Вышеописанные шаги отлично работали для Sun Application Server 9.1_1, но не для Oracle Glassfish 3.0.1.Я думаю, что это как-то связано с версией JSSE, используемой в ogs 3, по сравнению с версиями Sun App Server или jdk.Добавление нижеприведенной опции jvm к файлу ogs 3 domain.xml должно решить проблему, если простое добавление сертификата клиента в хранилище ключей не помогло.

<jvm-options>-Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol</jvm-options>

Я заметил, что кто-то сказал, что не использует jvmЗаявление о вариантах выше, но это часть исправления, не используйте его и посмотрите, работает ли оно, я готов поспорить, что это не так.Может быть, просто смена обработчиков - вот почему это работает?

Вот где я нашел подробности: http://onjava.com/pub/a/onjava/2001/05/03/java_security.html?page=4

Я также наткнулся на финальную проблему (только для ogs 3), если вы получаете ошибкивремя от времени я бы предлагал найти приложение InstallCert (оно там есть) и дать ему следующие параметры командной строки: я получал эти ошибки PKIX при каждой третьей попытке вызова веб-службы.

Надеюсь, это помоглокто-то еще.Подобные проблемы заставляют меня рвать на себе волосы:)

1 голос
/ 07 июня 2011

Вместо использования глобальных системных свойств, вы должны создать отдельный SSLContext для своего клиента. Тогда не имеет значения, работает он на сервере Glassfish или нет.

Вот вопрос, который должен быть актуален (о клиентских сертификатах для WS): Выбор SSL-сертификата клиента в Java

0 голосов
/ 30 июня 2014

Я наконец получил это.

Удалены все сертификаты из моего инструмента для ключей.

Пример команды: keytool -list -v -keystore keystore.jks -alias mydomain

Я преобразовал ответ сертификата с сервера в bas64 DER и скопировал их в один файл .PEM, и я загрузил .PEM в свой keytool:

Пример команды: keytool -importcert -keystore keystore.jks -alias mydomain -file my.pem

Затем я загрузил хранилище ключей:

KeyStore myStore = KeyStore.getInstance("JKS");
InputStream keyInputx = new FileInputStream("C:\\myStore.jks");
myStore.load(keyInputx, "xxx".toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyInputx.close();
/*Enumeration enumeration = myStore.aliases();
 while (enumeration.hasMoreElements()) {
     String alias = (String) enumeration.nextElement();
     System.out.println("alias name: " + alias);
     Certificate certificate = myStore.getCertificate(alias);
     System.out.println(certificate.toString());
 }*/
keyManagerFactory.init(myStore, "xxx".toCharArray());
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
SSLSocketFactory sockFact = context.getSocketFactory();

Множество ссылок вокруг, так что будьте счастливы использовать.

...