CertificateException: не найдено имя, соответствующее ssl.someUrl.de - PullRequest
40 голосов
/ 22 июня 2010

Я пытаюсь подключиться к одному из моих серверов через ssl, с Java.Я попробовал много вариантов, вот моя лучшая попытка:

Я генерирую jssecacerts с помощью сценария Recommendet: http://blogs.oracle.com/andreas/resource/InstallCert.java с помощью команды: java InstallCert ssl.someUrl.de changeit

после этого я повторил команду:

Loading KeyStore jssecacerts...
Opening connection to ssl.someUrl.de:443...
Starting SSL handshake...

No errors, certificate is already trusted

Server sent 1 certificate(s):

 1 Subject EMAILADDRESS=info@plesk.com, CN=plesk, OU=Plesk, O=Parallels, L=Hernd
on, ST=Virginia, C=US
   Issuer  EMAILADDRESS=info@plesk.com, CN=plesk, OU=Plesk, O=Parallels, L=Hernd
on, ST=Virginia, C=US
   sha1    f1 0d 2c 54 05 e1 32 19 a0 52 5e e1 81 6c a3 a5 83 0d dd 67
   md5     f0 b3 be 5e 5f 6e 90 d1 bc 57 7a b2 81 ce 7d 3d

Enter certificate to add to trusted keystore or 'q' to quit: [1]

Я скопировал файл в каталог по умолчанию и загрузил сертификат в Java. trustStore

System.setProperty("javax.net.ssl.trustStore", "C:\\Program Files (x86)\\Java\\jre6\\lib\\security\\jssecacerts");
System.setProperty("javax.net.ssl.trustStorePassword","changeit");

Затем я пытаюсь подключиться

URL url = new URL("https://ssl.someUrl.de/");
URLConnection conn = url.openConnection();
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));

И я получаю сообщение об ошибке в 3-й строке: (Не найдено совпадений с именем ssl.someUrl.de найдено)

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching ssl.someUrl.de found

Это причина получения сертификата plesk по умолчанию или что-то еще не так?

Настройка: JRE 6.20, Netbeans 6.8, Windows7 64bit

Ответы [ 6 ]

57 голосов
/ 22 июня 2010

Похоже, что сертификат сервера, к которому вы пытаетесь подключиться, не соответствует его имени хоста.

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

В HTTP это делается путем проверки того, что:

  • сертификат содержит запись альтернативного имени субъекта DNS (это стандартное расширение), соответствующую имени хоста;

  • в противном случае последний CN вашего выделенного имени субъекта (если хотите, это основное имя) совпадает с именем хоста. (См. RFC 2818.)

Трудно сказать, каково альтернативное имя субъекта, не имея сертификата (хотя, если вы подключитесь к своему браузеру и проверьте его содержимое более подробно, вы сможете увидеть его). Видимое имя субъекта выглядит так:

EMAILADDRESS=info@plesk.com, CN=plesk, OU=Plesk, O=Parallels, L=Herndon, ST=Virginia, C=US

(Таким образом, вместо CN = plesk должно быть указано CN = ssl.someUrl.de, если у вас уже нет альтернативного имени субъекта с DNS: ssl.someUrl.de; я полагаю, что вы не т.)

Вы можете обойти проверку имени хоста, используя HttpsURLConnection.setHostnameVerifier (..) . Не должно быть слишком сложно написать собственный HostnameVerifier, который обходит проверку, хотя я бы рекомендовал делать это только тогда, когда сертификат конкретно касается этого сертификата. Вы должны получить это, используя аргумент SSLSession и его метод getPeerCertificates ().

(Кроме того, вам не нужно устанавливать свойства javax.net.ssl. * Так, как вы это сделали, так как вы все равно используете значения по умолчанию.)

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

23 голосов
/ 02 сентября 2014

В Java 8 вы можете пропустить проверку имени сервера с помощью следующего кода:

HttpsURLConnection.setDefaultHostnameVerifier ((hostname, session) -> true);

Однако это следует использовать только в разработке!

14 голосов
/ 21 ноября 2015

Я создал метод fixUntrustCertificate (), поэтому, когда я имею дело с доменом, который не находится в доверенных центрах сертификации, вы можете вызвать метод перед запросом.Этот код будет работать после java1.4.Этот метод применяется для всех хостов:

public void fixUntrustCertificate() throws KeyManagementException, NoSuchAlgorithmException{


        TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                }

            }
        };

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };

        // set the  allTrusting verifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
}
4 голосов
/ 10 июля 2013

Я нашел хорошее разрешение здесь: http://www.mkyong.com/webservices/jax-ws/java-security-cert-certificateexception-no-name-matching-localhost-found/

Но моя проблема была немного другой и решала ее по-другому.

Веб-сервис был на удаленном хосте. Например: https://some.remote.host/MyWebService?wsdl

Но он был доступен только по IP для любых клиентов, но сертификат был создан для домена: some.remote.host (CN = some.remote.host). И этот домен не может быть разрешен по IP, потому что он не представлен в DNS).

Таким образом, возникла та же проблема: если я использую IP для подключения к веб-службе с помощью ssl, он не может быть достигнут, поскольку сертификат CN = some.remote.host и он не равен указанному имени хоста (т.е. IP-адрес хоста).

Я решил, сопоставив это имя хоста с IP в файле / etc / hosts. Проблема была исправлена.

Но в случае, если веб-служба размещена на сервере приложений localhost, она должна решаться так же, как mkyong, описанный в его статье.

1 голос
/ 08 апреля 2019

Если вы ищете ошибку Kafka, это может произойти из-за обновления версии Kafka с 1.x до 2.x.

javax.net.ssl.SSLHandshakeException: общая проблема SSLEngine ...javax.net.ssl.SSLHandshakeException: общая проблема SSLEngine ... java.security.cert.CertificateException: нет совпадения имени *** найдено

или

[Источник clientId = provider-1]Соединение с узлом -2 не прошло проверку подлинности из-за: сбоя рукопожатия SSL

Значение по умолчанию для ssl.endpoint.identification.algorithm было изменено на https, которое выполняет проверку имени хоста (человек-посредник)атаки возможны в противном случае).Установите ssl.endpoint.identification.algorithm в пустую строку, чтобы восстановить предыдущее поведение. Apache Kafka Значительные изменения в 2.0.0

Решение: SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, ""

1 голос
/ 25 июля 2013

Имя сервера должно совпадать с именем / фамилией, которое вы даете при создании сертификата

...