среда, 4 января 2012 г.

TomCat JAR SSL HTTPS варушыся


Настройка  защищенного (https/ssl) соединения между сервером (TomCat) и java JAR приложением

Генерирование ключей и хранилищ.
  • Хранилище сервера    
  • Хранилище клиента     

Настройка Сервера

Проверка работы сервера

Настройка Runnable jar приложения



             

      Необходимо:
- установленная JAVA начиная с 1.6
- установленный tomcat 6 (я тестировал на 6.0.20)
Для того что бы создать ключи и хранилища мы будем использовать стандартную утилиту Keytool.exe входящую в состав Java SDK.
Утилита интерактивная и задаёт достаточно много вопросов в сущности для нас имеющих не большое значение.
Из командной строки выполним следующую команду:

keytool -genkeypair -alias sever -keyalg RSA -validity 365 -keystore .store -storetype JKS
 Вопросы касающиеся имени и организации можно вводить не задумываясь и не запоминая. Главное это пароль который вводим в самом начале, и в конце когда спрашивают пароль на alias нужно просто нажать enter,что подтвердит наш пароль от хранилища как пароль для alias.
должно получится что то вроде:

Что в сущности мы имеем и что мы уже можем сделать?
У нас есть хранилище с ключом для шифрования передаваемых данных.
Мы можем настроить  TomCat на использование HTTPS соединения.Если остальная информация не играет роли то можно посмотреть настройку Tomcat здесь. Но для нормальной работы приложения которое будет взаимодействовать с нашим сервером нужно ещё кое что.

Для начала проверим существует ли наш сертификат:
keytool -list -alias sever -keystore .store
 вводим пароль который вводили ранее и должно быть что -то вроде:

sever, 04.01.2012, PrivateKeyEntry,
Certificate fingerprint (MD5): 94:E5:E0:62:A4:A6:54:8E:8D:AC:39:55:52:5B:BE:98

теперь  вкратце  немного теории:

для того что бы возможно было соединение между двумя объектами(сервер-клиент) нужно что бы у клиента был ключ , а у сервера этот же ключ должен находится в truststore ( доверенном хранилище)

1 у сервера есть просто keyStore
2 у сервера есть trustStore
3 у клиента есть ключ который так же экспортирован в trustStore
теория закончилась.
ранее мы создали keyStore для сервера, теперь создадим key для клиента
keytool -genkey -alias client -keyalg RSA -keystore .key -storetype JKS
все тоже самое как и в первом случае вводим пароль и данные.
уточню : если сейчас попробовать через браузер используя данные хранилища подключиться к серверу то ничего у нас не получится даже при наличии правильных настроек TomCat. дело в том что большинство браузеров не поддерживает данный тип хранилища (JKS).
если это будет критично то как тип хранилища нужно указать  -storetype PKCS12. Подробнее можно посмотреть здесь.

Теперь внимание : нам нужно достать созданный ключ из хранилища, поместить во временный файл, и импортировать в хранилище сервера:
keytool -export -alias client -keyalg RSA -keystore .key -file .temp
.temp и есть наш временный файл. Пароль нужен от клиентского хранилища.
Теперь создадим доверенное хранилище и импортируем туда наш ключ
keytool -import -alias client -keyalg RSA -keystore .trust -storetype JKS -file .temp
Что у нас получилось?
1 .store - хранилище ключей сервера
2 .trust - хранилище сервера для доверенных ключей клиента
3 .key - хранилище ключей клиента
4 .temp - файл куда мы импортировали ключик (далее не используется)

теперь настоятельно советую обновить свои знания в вопросе настройки TomCat для SSL соединения, например здесь. Так как ваши настройки (%TOMCAT%\conf\server.xml) после запуска некоторых проектов могут отличаться от default . На некоторых ресурсах предлагают комментирование некоторых элементов данной секции


<?xml version='1.0' encoding='utf-8'?>

<Server port="8005" shutdown="SHUTDOWN">

<!--APR library loader. Documentation at /docs/apr.html -->
        <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
<Listener className="org.apache.catalina.core.JasperListener" />
<!-- Prevent memory leaks due to use of particular java/javax APIs -->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html -->
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />


но на практике единственная строчка которую нужно закоментировать это -
       <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
и собственно сама настройка TomCat:
убедительная просьба сделать следующие шаги в заданном порядке:
1 Остановить TomCat
         В командной строке пишем:
           >cd  [путь_к вашей_директории_tomcat]\bin
           >shutdown.bat
2 Скопировать наши файлы с ключами (.store и .trust) в директорию с установленным TomCat. или далее нужно будет указывать путь к ним.
3 Открыть [путь_к вашей_директории_tomcat]\conf\server.xml в любом текстовом редакторе, если вы используете IDE то можно и в ней , тогда будет подсветка синтаксиса.
4 Находим секцию <Service name="Catalina">
   и в ней добавляем собственно наши настройки убедившись что таких же строчек более нигде нет:
======================================================================
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" maxHttpHeaderSize="8192" maxThreads="150"

minSpareThreads="25" maxSpareThreads="75" enableLookups="false"

disableUploadTimeout="true" acceptCount="100" scheme="https" secure="true"

clientAuth="true" sslProtocol="SSL" keystoreFile=".store"

keystorePass="tomcat" keystoreType="JKS" keyAlias="sever"

truststoreFile=".trust" truststorePass="password"

truststoreType="JKS" />
=======================================================================
clientAuth="true" - аутентификация на стороне клиента..!!!

keystoreFile="[путь]\.store"
truststoreFile="[путь]\.trust"       файлы содержащие наши ключи.

truststorePass="password"
keystorePass="password"           пароли  соответствующие  хранилищам.

keyAlias="sever" соответствует Alias хранилища keystoreFile.

 4 Запустить TomCat
         В командной строке пишем:
           >cd  [путь_к вашей_директории_tomcat]\bin
           >startup.bat

Настало время проверки нашего соединения:
Создадим новый или настроим существующий проект Java:
нами будут использованы следующие библиотеки:

import java.security.KeyStore;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

один из способов загрузки ключей:



FileInputStream storeKey =new FileInputStream("[путь к хранилищу клиента]..key");
KeyStore key = KeyStore.getInstance("JKS"); //тип ключа
key.load(storeKey, "password".toCharArray()); 
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(key, "password".toCharArray());


//теперь наш ключ клиента загружен и готов к использованию
поскольку аутентификация на стороне клиента то мы будем доверять всем сертификатам
в коде это выглядит так:


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("SSLv3");
                  sc.init(keyManagerFactory.getKeyManagers(), trustAllCerts,
                             new java.security.SecureRandom());


и два способа использования:
1 с помощью сокетов
SSLSocketFactory factory = (SSLSocketFactory) sc.getSocketFactory();
SSLSocket socket =  (SSLSocket) f.createSocket("localhost", 8443);

2 с помощью URLConnection
      HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

      //верификатор нужен для проверки подходит ли тело нашего сертификата хосту

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

      HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
      URL theURL = new URL("https://localhost:8443/");
      URLConnection urlConnection = theURL.openConnection();



Засим могу только предложить скачать архив:
 1 файл конфигурации tomcat
 2 war для деплоинга на сервер
 3 проект для jar
 4 файлы-хранилища ключей