2014-11-07 2 views
3

Насколько я понимаю, в большинстве случаев это исключение указывает, что владелец сертификата CN (общее имя) не совпадает с именем хоста в URL-адресе. Однако в моем случае они совпадают, но исключение до сих пор вызывает ..Почему я получаю «Не найдено совпадение имен» CertificateException?

удаленный сертификат иерархия сервера:

  1. самозаверенный сертификат с CN=sms.main.ru
  2. сертификат, подписанный с первым и CN=client.sms.main.ru

Мой Java-клиент запускается под Apache-Tomcat 6 и пытается подключиться к https://client.sms.main.ru/ и следующее исключение:

No name matching client.sms.main.ru found 

Оба сертификата добавляются в $JAVA_HOME/jre/lib/security/cacerts с помощью $JAVA_HOME/bin/keytool, как показано на How do you configure Apache/Tomcat to trust internal Certificate Authorities for server-to-server https requests в ответ по unixtippse.

Java-код довольно тривиальна:

URL url = new URL(strurl); 
HttpURLConnection con = (HttpURLConnection) url.openConnection(); 
con.setRequestMethod("GET"); 
con.setRequestProperty("Connection", "close"); 
con.setDoOutput(true); 
con.connect(); 

Что мне не хватает?


Интересно то, что когда я пытаюсь открыть URL с помощью браузера на ПК с Windows, это говорит о том, что сертификат не является доверенным, я добавляю его в список исключений браузера и она отлично работает. Похоже, что я добавил эти сертификаты в cacerts неправильно, так что java не может их использовать. Но я могу легко найти их по псевдониму или CN с:

$JAVA_HOME/bin/keytool -list -keystore $JAVA_HOME/jre/lib/security/cacerts | less 
+0

, если он самоподписан, тогда ему не будет доверять, так как иерархия не пройдет до TA –

+0

@Scary Wombat. Но я добавил их обоих в 'cacerts'..and отметил их там как надежные .. Этого недостаточно? Разве это не так, как нужно, чтобы доверять самозаверяющему сертификату? – horgh

+0

Вы используете неправильный класс для доступа к https – CharlieS

ответ

3

В конце концов все, что я должен был сделать:

  1. Отключить имя хоста проверка:

    // Create all-trusting host name verifier 
    HostnameVerifier allHostsValid = new HostnameVerifier() { 
        public boolean verify(String hostname, SSLSession session) { 
         return true; 
        } 
    }; 
    // Install the all-trusting host verifier 
    HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); 
    
  2. Убедитесь, что файл по умолчанию cacerts используется, так как при исследовании I tri ed для отключения проверки сертификата ssl и используемого кода, который можно найти в большом количестве потоков на SO (реализующий собственный X509TrustManager), то есть в Java: Overriding function to disable SSL certificate check. Этот код заменил по умолчанию SSLSocketFactory, который мне нужен. Поэтому мне пришлось удалить все эти вещи и использовать только код, запрещающий проверку имени хоста.

Я оставил HttpURLConnection. Не нужно заменять его HttpsURLConnection.

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

+0

Я бы будем рады видеть какие-либо комментарии о downvoting .. – horgh

+0

не уменьшалось, но отключить проверку имени хоста почти всегда не так. Его не следует рекомендовать в качестве решения. – eis

-4

Используйте HttpsURLConnection и SSLSocketFactory для выполнения SSL рукопожатия.

+0

Как это должно мне помочь? – horgh

+0

Попробуйте исследовать 'HttpsURLConnection'. Вы используете неправильный класс для выполнения SSL, так как сертификат представлен на сервере. Ваш код ничего не делает с сертификатом. Это будет, если вы будете использовать классы, которые я предложил. – CharlieS

+0

Спасибо, что пометили его, а не хороший способ поощрить помощь! – CharlieS

1

Это раньше, как я доверилась самоподписывающиеся сертификаты на коте

static private SSLSocketFactory newSslSocketFactory(String jksFile, char[] password) { 

    try { 
     KeyStore trusted = KeyStore.getInstance("JKS"); 
     InputStream in = StaticHttpsClient.class.getClassLoader().getResourceAsStream(jksFile); 
     try { 
      trusted.load(in, password); 
     } finally { 
      in.close(); 
     } 

     SSLSocketFactory socketFactory = new SSLSocketFactory(trusted); 
     HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER; 
     socketFactory .setHostnameVerifier((X509HostnameVerifier) hostnameVerifier); 
     return socketFactory; 
    } catch (Exception e) { 
     throw new AssertionError(e); 
    } 
} 

static protected ClientConnectionManager createClientConnectionManager(String jksFile, char[] password) { 
    SchemeRegistry registry = new SchemeRegistry(); 

    registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory())); 
    registry.register(new Scheme("https", 443, newSslSocketFactory(jksFile, password))); 
    return new SingleClientConnManager(registry); 

} 
+0

Спасибо, однако мне удалось найти более простое решение – horgh

Смежные вопросы