2012-05-30 8 views
0

Это как браузер имеет дело с сертификатом SSL при подключении к HTTPS-сайтРазница в работе с сертификатом ssl в отношении браузера и jvm?

  1. Когда я типа https://myDemoSite.com в браузере, прежде всего, мой браузер запрашивает сертификат от myDemoSite.com (из-за HTTPS), то myDemoSite отправить этот сертификат в браузер

  2. После браузер получает этот сертификат, браузер проверяет, является ли он подписан проверенным органом или не так, как Verisign

  3. Если да со второго этапа, то в качестве третьего шага он проверяет, является ли в.п. rtificate проблема имеет то же URL, который пользователь в браузере набранного

Теперь я соединяющий сайт HTTPS с помощью Java программы говорит HttpsConnectProg1.My вопрос, как programmei.e HttpsConnectProg1 будет иметь дело с этим сертификата, выданного с подключением по протоколу HTTPS сайта (хотя сертификат, выданный этим сайтом https, сертифицирован, т.е. подписан проверенным органом).

Я просто попробовал небольшую программу , подключающуюся к сайту https, который выдает сертификат. Я ожидал некоторой ошибки, например, ошибки sslhandshake или ошибки сертификата (так как я не добавлял этот сертификат в $ JAVA_HOME \ jre \ lib \ security), но, к моему удивлению, я не получил никаких ошибок.

Актуальным вопросом является HttpsConnectProg1 проверяет шаг 3, сделанный браузером, поскольку это очень важный шаг? Для справки, то здесь

import java.io.IOException; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.net.URLConnection; 
import java.util.Properties; 
import javax.net.ssl.HostnameVerifier; 
import javax.net.ssl.HttpsURLConnection; 
import javax.net.ssl.SSLSession; 


public class ConnectToDemoSite { 

/** 
* @param args 
*/ 
public static void main(String[] args) { 
    // TODO Auto-generated method stub 

    String urlStr = "https://www.myDemoSite.com/demo1/"; 
    URL url; 
    Properties reply = new Properties(); 
    try { 
     url = new URL(urlStr); 
     URLConnection conn = url.openConnection(); 
     if(conn instanceof HttpsURLConnection) 
     { 
     HttpsURLConnection conn1 = (HttpsURLConnection)url.openConnection(); 
      conn1.setHostnameVerifier(new HostnameVerifier() 
      {   
       public boolean verify(String hostname, SSLSession session) 
       { 
        return true; 
       } 
      }); 

     reply.load(conn1.getInputStream()); 
     } 
     else 
     { 
      conn = url.openConnection(); 
      reply.load(conn.getInputStream()); 
     } 
    } catch (MalformedURLException e) { 
     e.printStackTrace(); 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 
    System.out.println("reply is"+reply); 



} 

} 
+0

, выданный известным CA –

ответ

2

Когда вы делаете подключение к https:// URI с Java, он использует Java Secure Socket Extension (JSSE) (если вы действительно хотите использовать пользовательские реализации SSL/TLS, но это очень редко) ,

Существует несколько способов настройки управления доверием (в основном, с использованием пользовательских TrustManager), но в противном случае оно будет использовать определенное количество разумных настроек.

В вашем примере сертификат будет проверен с использованием по умолчанию SSLContext, сам настроены по умолчанию X509TrustManager с целевыми якорями, считанных из cacerts (смотрите таблицу в Customization section of the JSSE Ref. Guide).

По умолчанию JRE поставляется с рядом предварительно доверенных сертификатов CA (например, большинства браузеров или ОС) в cacerts, что обычно похоже на то, что вы найдете в браузерах. Вот что делает JSSE Ref. Руководство говорит об этом:

ВАЖНО: JDK поставляется с ограниченным количеством доверенных корневых сертификатов в/безопасности/cacerts файл/Lib. Поскольку задокументирован в keytool, вы должны поддерживать (то есть добавлять/удалять) сертификаты, содержащиеся в этом файле, если вы используете этот файл в качестве доверенного магазина.

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

Если сертификат доверен, он затем проверяет, является ли имя хоста действительным для предполагаемого URL. (Обратите внимание, что это не полный URL-адрес, но только имя хоста.)

Эти правила определены в RFC 2818 (the HTTPS specification), Section 3.1. (Java 7 еще не реализует RFC 6125, но правила очень похожи, особенно для HTTPS.) EDIT: Когда соединение установлено, URLConnection (и базовый SSLSession) задается с именем хоста сервера , Короче говоря, следуя правилам RFC 2818, он просматривает сертификат сервера для записи DNS в расширении имени альтернативного имени субъекта (SAN) сертификата, чтобы убедиться, что он соответствует имени узла, установленному для соединения, или найдите это имя в общем имени DN объекта сертификата (CN), если нет записи DNS SAN.

Проверка имени хоста обычно выполняется с помощью верификатора имени хоста по умолчанию. В вашем примере вы заменили верификатор по умолчанию на тот, который всегда возвращает true. Следовательно, эта проверка на самом деле не произойдет в вашем случае, и все будет принято (вы делаете это через отверстие безопасности).

Кроме того, проверка имени хоста по умолчанию, выполняемая на Java, следует за RFC 2818 более строго, чем количество браузеров. В частности, это не будет accept IP addresses in CNs.

(По той же причине, что и вы должны использовать верификатор имени хоста, который всегда возвращает true, вы не должны использовать доверительные управляющие, которые ничего не делают, так как вы увидите ряд примеров, предлагающих быстрый исправить некоторые сообщения об ошибках SSL.)

+0

Два вопроса, т.е. Question1: - Как вы сказали Если сертификат доверен, он затем проверяет, является ли имя хоста действительным для предполагаемого URL. Кажется, что certficates также содержит информацию о хосте, так что HttpsURLConnection может проверить, пытается ли хост в сертификатах совпадать с программой url. ПРАВИЛЬНО? Вопрос 2: - Как вы сказали. В вашем примере вы заменили верификатор по умолчанию тем, который всегда возвращает true, я сделал это, потому что у меня была какая-то странная ошибка, и я использовал самоподписанный сертификат. Я не являюсь хорошей практикой возвращать истину даже –

+0

в случае сертифицированного CA? –

+0

Я добавил немного больше о вопросе 1: он действительно сравнивает имя хоста с некоторой информацией в сертификате (расширение SAN или CN). Что касается вопроса 2, вы всегда должны проверять имя хоста; единственное исключение - если вы хотите связать конкретный сертификат вниз для определенного хоста, но вам придется предварительно проверить это исключение вручную (аналогично проверкам, которые вы делаете в Firefox, когда вы хотите добавить исключение вручную: d нужно посмотреть на сертификат, чтобы проверить, что вы ожидаете, используя другие надежные источники информации). – Bruno