2010-03-20 2 views
2

Я получаю странную ошибку при попытке использовать инструмент AXIS1.4 Wsdl2Java для создания клиентского кода для веб-службы, установленной на безопасном сайте IIS. Когда я запускаю инструмент, который я получаю следующее исключение SSL:Ошибка странного сертификата при попытке сгенерировать клиента веб-сервиса с защищенного сайта

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No 
name matching XXXXXXX.net found 
     at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174) 
     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1 
591) 
     at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:187) 
     at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:181) 
     at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Clien 
tHandshaker.java:975) 
     at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHa 
ndshaker.java:123) 
     at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:5 
16) 
     at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.jav 
a:454) 
     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.j 
ava:884) 
     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SS 
LSocketImpl.java:1096) 
     at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketIm 
pl.java:1123) 

Weird является то, что эта ошибка возникает только тогда, когда я бегу WSDL2Java, и только для этого конкретного сервера. У меня есть другой веб-сервер с одинаковой настройкой, и там все прекрасно работает. Я triple проверил все keystores, и похоже, что все сертификаты CA загружены правильно. Я попытался использовать другой сервер с одинаковой настройкой и смог без проблем создать код прокси-сервера клиента. Странно, что если я использую код, сгенерированный с другого сервера, против странного сервера, все работает нормально. Только проблема Wsdl2Java вызывает у меня проблему.

ответ

1

Вероятно, существует несоответствие между DNS-именем хоста (например, machine1.mydomain.tld) ​​и значением CommonName из сертификата, следовательно, CertificateException. Из этого blog post:

  • , если вы хотите подключиться через IP, используя в качестве имени хоста;
    ваш сертификат должен включать это значение ip как значение альтернативного имени объекта (типа IPAddress: key = 7).
  • Если вы хотите подключиться через DNS в качестве имени хоста;
    ваш сертификат должен включать это DNS-имя в качестве альтернативного имени объекта (типа DNS: key = 2) или в качестве значения CommonName (CN).
+0

@ Паскаль не очень, если это было простое несоответствие доменных имен, браузеры будут жаловаться, а код, созданный на другом сервере, тоже будет жаловаться. – Vlad

+0

@ Vlad Java и браузеры могут не использовать один и тот же алгоритм. И, возможно, сгенерированный код содержит реализацию «HostnameVerifier», поэтому это ничего не доказывает. Вы проверили CN в сертификате? –

+0

CN правильный. Это было первое, что я проверил. – Vlad

0

Если у вас есть сертификат сервера под рукой и OpenSSL установлена, вы можете сбросить содержимое сертификата с чем-то вроде:

$ openssl x509 -noout -text -in filename-here.pem 

Вы увидите «CN =» как часть Subject, и если у него есть расширение altSubjectName в сертификате, вы увидите, что ниже под расширениями X509v3, как X509v3 Subject Alternative Name, и вы будете искать что-то вроде DNS: host-name-here.

Если это совпадает с именем хоста, с которым вы подключаетесь, просто проверьте, подключаетесь ли вы по IP-адресу или по имени хоста в любом SSL-интерфейсе, который вы проходите, и убедитесь, что это по имени хоста, а не по IP-адресу.

Если в сертификате нет соответствующего имени (которое соответствует имени хоста, к которому вы подключаетесь), некоторые интерфейсы SSL позволят вам игнорировать «несоответствие имен». (Я не знаю, как это сделать в вашем конкретном случае.)

EDIT:

Попробуйте подключиться по имени хоста вместо IP-адреса и посмотреть, если есть разница.

Если IP-адрес указан в сертификате, вы увидите что-то вроде IP: xx.xx.xx.xx под X509v3 Subject Alternative Name в выводе openssl.

Если IP не указан, запустите nslookup из командной строки и сравните выходные данные для рабочих и нерабочих адресов сервера. Это может быть, как рабочий сервер соответствует имени хоста (т. Е. Посредством getnetbyaddr).

EDIT 2:

Вы пробовали подключения по имени хоста (в вашей строке соединения) и все еще получаю ту же ошибку? Не имеет значения, работает ли соединение через браузер с использованием IP-адреса - браузер может не проверять имя хоста, используя тот же алгоритм. Вы пытались подключиться к хорошему серверу, используя IP-адрес в соединении? Кроме того, смотрите здесь, чтобы попробовать: found with quick Google

+0

CN правильный, и я подключаюсь по IP-адресу. Это не простая проблема несоответствия имени. Если это так, браузеры и сгенерированный код будут жаловаться. Проблема возникает только с WSDL2Java – Vlad

0

Проблема заключается в том, что WSDL2Java отклонил сертификат Сервера из-за имени. В Java имя хоста, которое вы используете для подключения к удаленной системе, в значительной степени соответствует общему имени в сертификате. Он не будет отменять поиск по IP-адресу. Вы должны подключиться, используя имя хоста.

Другие ответы указывают, что вы подключаетесь через IP-адрес. Это не правильный способ сделать что-то. Java проверяет сертификат на имя хоста, с которым он подключается.

Если вы подключаетесь с использованием IP-адреса, у вас может не быть настроенной DNS в вашей среде. Самый простой способ обойти это - добавить имя хоста в ваш файл hosts. В Windows это находится в папке «C: \ Windows \ System32 \ drivers \ etc \ hosts».

xx.xx.xx.xx  XXXXXXXXXX.net 

Это позволит вам использовать имя хоста, чтобы получить WSDL через WSDL2Java.

Альтернатива:

Существует альтернатива, если это до сих пор не работает. Загрузите файл .wsdl с помощью веб-браузера. Создайте WSDL2Java свои Java-заглушки из локального файла на диске, а не на веб-сервере. Сгенерированный код будет идентичным, но ему не придется проходить через SSL, чтобы получить WSDL.

+0

. Пожалуйста, внимательно прочитайте описание проблемы. Имя хоста соответствует сертификату CN = name. Таким образом, все браузеры и даже сгенерированный клиентский код работают нормально. WSDL2Java - это единственное, что не работает против этого конкретного сервера. Мне удалось создать клиентский код на другом сервере, который я использовал для разработки, который имеет идентичный набор программного обеспечения. Единственное различие между двумя серверами заключается в том, что производство (которое не работает) использует сертификат, подписанный GlobalSign, и в разработке используется сертификат, подписанный CACert.org – Vlad

+0

. Когда тот же WSDL2Java подключается к хорошему серверу, вы также подключаетесь по IP-адресу? Вы пробовали подключиться по имени хоста в сломанном случае, и он все еще не работает? (С WSDL2Java-соединением, а не просто с браузером.) В этом случае я бы проверял, отличаются ли расширения сертификатов X509 между сертификатами, в частности Key Usage и Extended Key Usage, но это просто выстрел в темноте. –

0

Возможно, вам не хватает соответствующего GlobalSign root certificate for Java.

# Import a root or intermediate CA certificate to an existing Java keystore 
keytool -import -trustcacerts -alias root -file Thawte.crt -keystore keystore.jks 

Другая возможность относится к комбинации корневого и промежуточного сертификатов. Больше от GlobalSign website:

«Некоторые приложений Apache и Java на основе требуют корень и промежуточные сертификаты, чтобы быть в комплекте один сертификат ...»

1

Вы можете найти с помощью системы отладки SSL свойство может быть полезно для изучения этой проблемы:

-Djavax.net.debug=ssl 

Если есть слишком много распечатывается, вы можете ФИЛТР эр некоторые вещи, возможно, это:

-Djavax.net.debug=ssl,trustmanager 

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