пятница, 2 марта 2012 г.

Настройка axis клиента на работу с несколькими хостами по протоколу https c клиентскими сертификатами

Итак, пока есть время, быстренько опишу этот опыт.

Axis, использует системные настройки для осуществления соединения по https, т.е. теоретически можно указать системные свойства

System.setProperty("javax.net.ssl.keyStore", "securirty/cacerts");
System.setProperty("javax.net.ssl.keyStorePassword", "");
System.setProperty("javax.net.ssl.trustStore", "security/cacerts");

и клиент будет их использовать, что вполне допустимо, если нужно соединение только с одним хостом. Но что делать, если нужно коннектиться к нескольким хостам, к каждому с разными сертификатами, причем эти сертификаты находятся в разных хранилищах и имеют разные пароли? Вариантов решения проблемы два: первый - использовать jax-ws для генерации клиента, и дальше идет черная магия с конфигурацией, либо использовать свою SSLConnectionFactory, но завязываться на имя хоста. Какой их этих путей лучше, не знаю, я выбрал решение с созданием SSLConnectionFactory, как более простое. идея и часть кода взята отсюда

Итак, создаем стандартных axis клиентов по wsdl файлам, для каждого хоста получатся свои классы клиента. Далее, перед вызовом методов веб сервиса необходимо установить свойство

AxisProperties.setProperty("axis.socketSecureFactory", "org.yourcompany.packagename.CustomSSLSocketFactory");

Содержимое файла CustomSSLSocketFactory.java примерно следующее:

package org.yourcompany.packagename;

import org.apache.axis.components.net.BooleanHolder;
import org.apache.axis.components.net.JSSESocketFactory;
import org.apache.axis.components.net.SecureSocketFactory;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import java.io.FileInputStream;
import java.net.Socket;
import java.security.KeyStore;
import java.util.Hashtable;

/**
 * Custom SSL socket factory to use our integrated keystore.
 * 

* Based loosely on org.apache.axis.components.net.SunJSSESocketFactory */ public class CustomSSLSocketFactory extends JSSESocketFactory implements SecureSocketFactory { private static final String FILE_SEPARATOR = System.getProperty("file.separator"); private static final String KEYSTORE_PATH = System.getProperty("java.home") + FILE_SEPARATOR + "lib" + FILE_SEPARATOR + "security" + FILE_SEPARATOR; public CustomSSLSocketFactory(Hashtable attributes) { super(attributes); } @Override public Socket create(String host, int port, StringBuffer otherHeaders, BooleanHolder useFullURL) throws Exception { sslFactory = createSSlSocketFactory(host); return super.create(host, port, otherHeaders, useFullURL); } private SSLSocketFactory createSSlSocketFactory(String host) throws Exception { String keystorePass = null; String keystorePath = null; if (host.equals("google.com")){ keystorePass = "passforgoogle"; keystorePath = "googlestore.jks"; } else if (host.equals("yandex.com")) { keystorePass = "passforyandex"; keystorePath = "yandexstore.jks"; } else if (host.equals("yahoo.com")) { keystorePass = "passforyahoo"; keystorePath = "yahoostore.jks"; } if (keystorePass == null || keystorePath == null) { System.out.println("unknown host "+ host +", cannot create socket factory"); return null; } char[] keystorepass = keystorePass.toCharArray(); FileInputStream is = new FileInputStream(KEYSTORE_PATH + keystorePath); // create required keystores and their corresponding manager objects KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(is, keystorepass); is.close(); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(keyStore, keystorepass); SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(kmf.getKeyManagers(), null, null); return sslContext.getSocketFactory(); } }

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

Следующей на очереди будет описание работы с библиотекой шифрования Signal COM.

Комментариев нет:

Отправить комментарий