Связь SSL, насколько это может быть сложно? - PullRequest
0 голосов
/ 04 марта 2009

На моем ПК запущено основное приложение Java, которое может отправлять данные XML на сервлет и получать данные XML обратно. http://iamt.wisconsin.gov/IAM-WiEntUser/WiEntUserService?xml=

Я могу использовать https://iamt.wisconsin.gov/IAM-WiEntUser/WiEntUserService?xml= из IE и Firefox, потому что они позволили мне загрузить личный сертификат.

Я хочу использовать https из основного приложения Java, потому что некоторые данные являются конфиденциальными. Я получаю IOException с MSG = неизвестный сертификат. Хорошо, это имеет смысл, Java не знает о закрытом сертификате.

Я надеялся, что это будет так же просто, как сказать Java доверять сертификатам FireFox. System.setProperty ( "javax.net.ssl.trustStore", «C: / Documents and Settings / кэндайм / Данные приложения / Mozilla / Firefox / Profiles / 6f8ggdi7.default / cert8.db»); Но это дает IOException с MSG = неверный формат хранилища ключей.

Связь по SSL, насколько это сложно? Я провел целых восемь часов, пытаясь найти способ сделать это. Кажется, это так просто, что это не документировано или очень сложно, и ни у кого нет хорошего примера.

Справка.

Ответы [ 4 ]

4 голосов
/ 04 марта 2009

Формат хранилища ключей Mozilla cert8.db по умолчанию не читается (хотя можно «подключить» провайдера, который может его анализировать). Проще всего импортировать сертификат в хранилище ключей, которое поддерживается по умолчанию. 1001 *

Для начала вам нужна копия сертификата.

В Firefox перейдите на соответствующую страницу. Нажмите значок «Блокировка» в строке состояния в правом нижнем углу окна. В появившемся диалоговом окне нажмите кнопку «Просмотреть сертификат». Новый диалог появится; выберите вкладку «Подробности». Нажмите кнопку «Экспорт» в нижней части окна, чтобы сохранить сертификат в файл (используйте формат DER или PEM).

Теперь вам нужно получить сертификат в формате хранилища ключей, используемом Java.

Используйте утилиту JDK keytool:

keytool -import -keystore mykeystore.jks -alias iamt -file iamt.wisconsin.gov

Когда будет запрошен пароль, выберите новый пароль, который позже можно будет использовать для проверки того, что сертификаты в хранилище ключей не были подделаны. Затем keytool предложит вам доверять новому сертификату - введите yes! У вас должен быть новый файл хранилища ключей Java с именем «mykeystore.jks» (или что вы выберете).

Теперь запустите вашу программу, указав новый файл хранилища ключей в качестве значения свойства "javax.net.ssl.trustStore".


Кстати, я заметил, что вы возвращаете вывод Java Beans XMLEncoder из вашего сервиса. Этот формат "Long Term Persistence" является пропущенной драгоценностью JDK, но он небезопасен для анализа ненадежного контента. Используя этот синтаксис, любой метод может быть вызван в JVM, выполняющем анализ. Это похоже на «eval» с ненадежным JSON. Таким образом, если бы я реализовывал клиентскую службу, я бы, вероятно, не захотел бы проанализировать результат из службы без большой дополнительной работы, чтобы «вставить в песочницу» синтаксический анализ как ненадежный код. И я предполагаю, что служба анализирует один и тот же формат в запросах, что также опасно для сервера.


Когда вы задаете вопрос о сообщении об ошибке, хорошей идеей будет опубликовать все сообщение, включая трассировку стека (если это не java.lang.StackOverflowError!). Это может быть бессмысленно для вас, но часто в нем есть информация, необходимая для мгновенного выявления проблемы.

1 голос
/ 04 марта 2009

Я смог использовать самозаверяющий сертификат, как только зарегистрировал его в Java с помощью keytool.

См. Это руководство: http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/keytool.html

По сути, вы: 1. Создайте самозаверяющий сертификат 2. Экспортируйте его в файл 3. Импортируйте его в хранилище ключей по умолчанию

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

1 голос
/ 04 марта 2009

Насколько я понимаю, проблема в том, что Java не будет принимать самозаверяющий сертификат. Поправь меня, если я ошибаюсь!

Вы пытались использовать Commons-HttpClient ? У этого есть еще несколько опций, и на этой странице есть руководство для принятия самозаверяющих сертификатов. Также см. этот пример кода

Редактировать: здесь есть руководство по импорту сертификата в Java здесь - очевидно, вам придется делать это на каждой машине, на которой работает приложение Java. Опция HttpClient может быть более гибкой, в зависимости от того, что вам нужно.

0 голосов
/ 04 марта 2009
  1. Экспорт сертификата из IE в формате X.509 (.CER) в кодировке Base-64
  2. Запустите keytool для экспортированного сертификата. Укажите файл trustStore и пароль. Ответьте «да» на вопрос доверия. keytool -import -v -trustcacerts -alias IamtCert -file C: \ Work \ IAM \ Acceptance \ IamAcceptanceCertificate.cer -keystore N: \ WEB \ DEG \ CaCert.dat
  3. Добавьте две строки кода. System.setProperty ( "javax.net.ssl.trustStore", "N: \ Web \ ДЭГ \ CaCert.dat"); System.setProperty ( "javax.net.ssl.trustStorePassword", "хххххх");

Не сложно, если ты знаешь, что делать. Остальная часть кода остается прежней. (У сервлета есть другой способ проверки вызывающего абонента, который не включает сертификат.)

    urlAddress += encodedXmlData;
    URL  url = null;
    HttpURLConnection connection = null;
    StringBuffer result = new StringBuffer();
    try {
        url = new URL( urlAddress );
        connection = (HttpURLConnection)url.openConnection();
    }
    catch( IOException ioe ) {
        System.out.println(classMethod+": IOException: URL Msg="+ioe.getMessage() );
        return(null);
    }           
    connection.setDoInput(true);    // Default value.
    connection.setDoOutput(true);   // Not the default value.
    connection.setUseCaches(false); // Not the default value.
    try {
        connection.setRequestMethod("POST");  // Large pay load.
    }
    catch( ProtocolException pe ){
        System.out.println(classMethod+": ProtocolException: URL Msg="+pe.getMessage() );
        return(null);
    }
    // If true, this URL is being examined in a context in which it makes
    // sense to allow user interactions such as popping up an 
    // authentication dialog.
    connection.setAllowUserInteraction(false);
    try {
        connection.connect();
        BufferedReader bufferedReader = new BufferedReader( new
                InputStreamReader( connection.getInputStream() ) );

        // Retrieve the response
        String inputLine = null;
        while ( (inputLine = bufferedReader.readLine() ) != null ) {
            if ( inputLine.indexOf("</void>") > -1 ) inputLine+='\n';
            result.append(inputLine);
        }
        bufferedReader.close();
        connection.disconnect();
    }
    catch( IOException ioe) {
        System.out.println(classMethod+": IOException: Read Msg="+ioe.getMessage() );
        return(null);
    }
...