У меня есть клиент веб-службы Java, который использует веб-службу через HTTPS.
import javax.xml.ws.Service;
@WebServiceClient(name = "ISomeService", targetNamespace = "http://tempuri.org/", wsdlLocation = "...")
public class ISomeService
extends Service
{
public ISomeService() {
super(__getWsdlLocation(), ISOMESERVICE_QNAME);
}
Когда я подключаюсь к URL-адресу службы ( https://AAA.BBB.CCC.DDD:9443/ISomeService
), я получаю исключение java.security.cert.CertificateException: No subject alternative names present
.
Чтобы исправить это, я сначала запустил openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txt
и получил следующее содержимое в файле certs.txt
:
CONNECTED(00000003)
---
Certificate chain
0 s:/CN=someSubdomain.someorganisation.com
i:/CN=someSubdomain.someorganisation.com
-----BEGIN CERTIFICATE-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=someSubdomain.someorganisation.com
issuer=/CN=someSubdomain.someorganisation.com
---
No client certificate CA names sent
---
SSL handshake has read 489 bytes and written 236 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-MD5
Server public key is 512 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : RC4-MD5
Session-ID: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Session-ID-ctx:
Master-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Key-Arg : None
Start Time: 1382521838
Timeout : 300 (sec)
Verify return code: 21 (unable to verify the first certificate)
---
AFAIK, теперь мне нужно
- извлеките часть
certs.txt
между-----BEGIN CERTIFICATE-----
и-----END CERTIFICATE-----
, - измените его так, чтобы имя сертификата было равно
AAA.BBB.CCC.DDD
и - затем импортируйте результат с помощью
keytool -importcert -file fileWithModifiedCertificate
(гдеfileWithModifiedCertificate
- результат операций 1 и 2).
Это верно?
Если да, то как именно заставить сертификат из шага 1 работать с IP-адресом adddress ( AAA.BBB.CCC.DDD
)?
Обновление 1 (23.10.2013 15:37 МСК): В ответ на аналогичный вопрос я прочитал следующее:
Если вы не контролируете этот сервер, используйте его имя хоста (при условии, что в существующем сертификате есть хотя бы CN, соответствующий этому имени хоста).
Что именно означает «использовать»?
источник
У меня такая же проблема и я решил с этим кодом. Я поместил этот код перед первым вызовом моих веб-сервисов.
Все просто и отлично работает.
Вот первоисточник.
источник
return hostname.equals("localhost");
, если это то, что вы хотите сделать. Этоif
совершенно лишнее.HttpsURLConnection connection = (HttpsURLConnection) obj.openConnection();
. Кроме того, игнорирует ли это каждый сертификат? Поскольку я видел, что такой обходной путь уязвим для безопасности. Спасибо!Это старый вопрос, но у меня была такая же проблема при переходе с JDK 1.8.0_144 на jdk 1.8.0_191
Мы нашли подсказку в журнале изменений:
Журнал изменений
мы добавили следующее дополнительное системное свойство, которое в нашем случае помогло решить эту проблему:
источник
Проверка подлинности сертификата выполняется по тому, что запрашивает клиент.
Когда ваш клиент использует
https://xxx.xxx.xxx.xxx/something
(гдеxxx.xxx.xxx.xxx
- IP-адрес), удостоверение сертификата проверяется по этому IP-адресу (теоретически, только с использованием расширения IP SAN).Если в вашем сертификате нет IP SAN, но есть DNS SAN (или, если нет DNS SAN, общее имя в DN субъекта), вы можете заставить это работать, заставив ваш клиент использовать URL-адрес с этим именем хоста вместо этого (или именем хоста). для которого сертификат будет действителен, если существует несколько возможных значений). Например, если у вашего сертификата есть имя
www.example.com
, используйтеhttps://www.example.com/something
.Конечно, вам понадобится это имя хоста для разрешения на этот IP-адрес.
Кроме того, если есть какие-либо DNS SAN, CN в DN субъекта будет проигнорирован, поэтому в этом случае используйте имя, которое соответствует одному из DNS SAN.
источник
http://www.example.com/someservice
. Верно ли, что для того, чтобы сертификат работал с IP-адресом (https://AAA.BBB.CCC.DDD:9443/ISomeService
), мне нужно установить всеCN
поля наAAA.BBB.CCC.DDD
(заменитьsomeSubdomain.someorganisation.com
наAAA.BBB.CCC.DDD
в приведенном выше файле) и импортировать полученный файл сертификата?/etc/hosts
файл или его эквивалентЧтобы импортировать сертификат:
openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txt
это извлечет сертификаты в формате PEM.openssl x509 -in certs.txt -out certs.der -outform DER
sudo keytool -importcert -file certs.der -keystore <path-to-cacerts>
пароль cacerts по умолчанию - changeit.Если сертификат выдан для полного доменного имени, и вы пытаетесь подключиться по IP-адресу в своем Java-коде, то это, вероятно, следует исправить в вашем коде, а не вмешиваться в сам сертификат. Измените свой код для подключения по FQDN. Если полное доменное имя не разрешается на вашем компьютере разработчика, просто добавьте его в файл хостов или настройте свой компьютер с DNS-сервером, который может разрешить это полное доменное имя.
источник
Я исправил эту проблему правильным образом, добавив альтернативные имена субъектов в сертификат, вместо того, чтобы вносить какие-либо изменения в код или отключать SSL, в отличие от того, что предлагают здесь другие ответы. Если вы ясно видите, что в исключении говорится, что «Альтернативные имена субъектов отсутствуют», правильным способом будет их добавление.
Пожалуйста, перейдите по этой ссылке, чтобы понять шаг за шагом .
Вышеупомянутая ошибка означает, что в вашем JKS-файле отсутствует необходимый домен, на котором вы пытаетесь получить доступ к приложению. Вам потребуется использовать Open SSL и ключевой инструмент для добавления нескольких доменов.
echo '[ subject_alt_name ]' >> openssl.cnf
echo 'subjectAltName = DNS:example.mydomain1.com, DNS:example.mydomain2.com, DNS:example.mydomain3.com, DNS: localhost'>> openssl.cnf
openssl req -x509 -nodes -newkey rsa:2048 -config openssl.cnf -extensions subject_alt_name -keyout private.key -out self-signed.pem -subj '/C=gb/ST=edinburgh/L=edinburgh/O=mygroup/OU=servicing/CN=www.example.com/emailAddress=postmaster@example.com' -days 365
Экспортируйте файл открытого ключа (.pem) в формат PKS12. Вам будет предложено ввести пароль
Создайте .JKS из самоподписанного PEM (хранилища ключей)
Создайте сертификат из указанного выше хранилища ключей или файла JKS
Поскольку указанный выше сертификат является самоподписанным и не проверяется центром сертификации, его необходимо добавить в Truststore (файл Cacerts находится в расположении ниже для MAC, для Windows узнайте, где установлен JDK).
Оригинальный ответ размещен по этой ссылке здесь .
источник
Возможно, вы не захотите отключать всю проверку ssl, поэтому вы можете просто отключить проверку hostName с помощью этого, что немного менее страшно, чем альтернатива:
[РЕДАКТИРОВАТЬ]
Как упоминалось conapart3
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
, теперь устарело, поэтому его можно удалить в более поздней версии, поэтому в будущем вы можете быть вынуждены откатить свой собственный, хотя я бы все же сказал, что я бы держался подальше от любых решений, в которых вся проверка отключена.источник
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
устарела.Моя проблема с получением этой ошибки была решена путем использования полного URL «qatest.ourCompany.com/webService» вместо просто «qatest / webService». Причина заключалась в том, что в нашем сертификате безопасности был подстановочный знак, например «* .ourCompany.com». Как только я ввел полный адрес, исключение исчезло. Надеюсь это поможет.
источник
Ответили на него уже в https://stackoverflow.com/a/53491151/1909708 .
Это не удается, потому что ни общее имя сертификата (
CN
в сертификацииSubject
), ни какое-либо из альтернативных имен (Subject Alternative Name
в сертификате) не совпадают с целевым именем хоста или IP-адресом.Например, из JVM при попытке подключиться к IP-адресу (
WW.XX.YY.ZZ
), а не к DNS-имени ( https://stackoverflow.com ), HTTPS-соединение не удастся, потому что сертификат, хранящийся в хранилище доверенных сертификатов Java,cacerts
ожидает общего имени (или альтернативное имя сертификата, например stackexchange.com или * .stackoverflow.com и т. д.), чтобы соответствовать целевому адресу.Пожалуйста, проверьте: https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#HostnameVerifier
Выше передан реализованный
HostnameVerifier
объект, который всегда возвращаетtrue
:источник
Для весенней загрузки
RestTemplate
:org.apache.httpcomponents.httpcore
зависимостьиспользовать
NoopHostnameVerifier
для фабрики SSL:источник
Я получил этот вопрос после того, как получил такое же сообщение об ошибке. Однако в моем случае у нас было два URL-адреса с разными поддоменами ( http://example1.xxx.com/someservice и http://example2.yyy.com/someservice ), которые были направлены на один и тот же сервер. На этом сервере был только один подстановочный сертификат для домена * .xxx.com. При использовании сервиса через второй домен найденный сертификат (* .xxx.com) не совпадает с запрошенным доменом (* .yyy.com) и возникает ошибка.
В этом случае мы не должны пытаться исправить такое сообщение об ошибке, снижая безопасность SSL, а должны проверить сервер и сертификаты на нем.
источник
источник
Я использовал двухсторонний SSL в Springboot. Я выполнил все правильные настройки сервера tomcat службы и вызывающей службы RestTemplate. но я получал сообщение об ошибке «java.security.cert.CertificateException: нет альтернативных имен субъектов»
Пройдя через решения, я обнаружил, что JVM нужен этот сертификат, иначе он выдает ошибку установления связи.
Теперь, как добавить это в JVM.
перейдите в файл jre / lib / security / cacerts. нам нужно добавить файл сертификата нашего сервера в этот файл cacerts jvm.
Команда для добавления сертификата сервера в файл cacerts через командную строку в Windows.
C: \ Program Files \ Java \ jdk1.8.0_191 \ jre \ lib \ security> keytool -import -noprompt -trustcacerts -alias sslserver -file E: \ spring_cloud_sachin \ ssl_keys \ sslserver.cer -keystore cacerts -storepass changeit
Проверьте, установлен ли сертификат сервера:
C: \ Program Files \ Java \ jdk1.8.0_191 \ jre \ lib \ security> keytool -list -keystore cacerts
вы можете увидеть список установленных сертификатов:
для получения дополнительной информации: https://sachin4java.blogspot.com/2019/08/javasecuritycertcertificateexception-no.html
источник
добавить запись хоста с IP, соответствующим CN в сертификате
CN = someSubdomain.someorganisation.com
теперь обновите ip с именем CN, где вы пытаетесь получить доступ к URL-адресу.
У меня это сработало.
источник
источник
Если у вас есть сертификат как с CN, так и с альтернативными именами субъектов (SAN), если вы делаете запрос на основе содержимого CN, то этот конкретный контент также должен присутствовать в SAN, в противном случае он завершится с ошибкой.
В моем случае у CN было что-то, у SAN было что-то еще. Мне пришлось использовать URL-адрес SAN, и тогда он работал нормально.
источник
Добавьте свой IP-адрес в файл hosts, который находится в папке C: \ Windows \ System32 \ drivers \ etc. Также добавьте IP и доменное имя IP-адреса. пример: aaa.bbb.ccc.ddd abc@def.com
источник
Я решил вопрос следующим образом.
1. Создание класса. В классе есть пустые реализации
2. Создание метода
источник