Как настроить клиент Apache CXF для использования WebSphere truststore? (Получение исключения" не найден доверенный сертификат".)
во-первых, я начну с резюме. Я использую клиент Apache CXF для связи по SSL с поставщиком услуг Apache CXF, который использует самозаверяющий сертификат. Я импортировал сертификат в WebSphere truststore на клиентском сервере, но я все еще получаю "javax.сеть.ssl.SSLHandshakeException: SSLHandshakeException вызов https://somesvcprovider.com/appname/svc/myservice: com.компания IBM.jsse2.утиль.h: не найден доверенный сертификат" исключение.
Теперь, вот подробности:
у меня есть клиент веб-службы Apache CXF, который я настраиваю с помощью Spring, и клиент развертывается на сервере приложений WebSphere 6.1. Клиент CXF взаимодействует с поставщиком услуг Apache CXF на другом сервере WebSphere. Связь использует SSL.
поставщик услуг использует самозаверяющий сертификат. Я импортировал сертификат поставщика в WebSphere truststore на клиенте сервер через административную консоль. Я выполнил это, перейдя в SSL-сертификат и управление ключами > конфигурации SSL > NodeDefaultSSLSettings > хранилища ключей и сертификаты > NodeDefaultTrustStore > сертификаты подписавшего; затем я использовал инструмент "получить из порта" для импорта сертификата.
однако я все еще получаю эту ошибку при попытке связаться с поставщиком услуг: "javax.сеть.ssl.SSLHandshakeException: вызов SSLHandshakeException https://somesvcprovider.com/appname/svc/myservice: com.компания IBM.jsse2.утиль.h: доверенный сертификат не найден".
файл конфигурации Spring выглядит следующим образом:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://cxf.apache.org/configuration/security"
xmlns:http="http://cxf.apache.org/transports/http/configuration"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://cxf.apache.org/configuration/security
http://cxf.apache.org/schemas/configuration/security.xsd
http://cxf.apache.org/transports/http/configuration
http://cxf.apache.org/schemas/configuration/http-conf.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<http:conduit name="*.http-conduit">
<!-- deactivate HTTPS url hostname verification (localhost, etc) -->
<!-- WARNING ! disableCNcheck=true should not used in production. -->
<http:tlsClientParameters disableCNCheck="true" />
</http:conduit>
<!-- Read properties from property file(s). -->
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!-- The *.spring.properties files are prefixed with a system property
that is set on the WebSphere server. -->
<value>classpath:spring.${my.env}.properties</value>
</list>
</property>
</bean>
<jaxws:client id="myServiceClient"
serviceClass="com.client.stub.cxf.IMyService"
address="${my.svc.url}" />
<bean id="myReport" class="com.client.MyReportRequestor">
<property name="client" ref="myServiceClient"/>
</bean>
</beans>
как показано выше, клиент CXF вводится через сеттер весной. Код для связи с сервисом приведен ниже:
List<String> formNames = client.retrieveNames(formIdsList);
кроме того, я не знаю, связано ли это, но менеджеры доверия не возвращаются, когда я проверяю объект TLSClientParameters на клиенте CXF во время выполнения. Код для проведения проверки приведен ниже:
// Get the trust managers for this client.
Client proxy = ClientProxy.getClient(client);
HTTPConduit conduit = (HTTPConduit) proxy.getConduit();
TLSClientParameters tls = conduit.getTlsClientParameters();
TrustManager[] trustManagers = tls.getTrustManagers(); // trustManagers is null
есть ли что-нибудь еще, что мне нужно сделать, чтобы заставить клиента Apache CXF доверять самозаверяющему сертификату?
Я предпочитаю не указывать путь к truststore вместе с паролем в файле конфигурации.
спасибо!
4 ответов
Я не думаю, что вы можете использовать хранилища ключей WAS так же, как с внешним компонентом (Apache CXF). Вы, вероятно, должны построить и использовать ваш собственный TrustManager. Кажется, есть несколько рабочих примеры рядом.
CXF, вероятно, использует неправильную фабрику сокетов SSL.
попробуйте добавить это в конфигурацию Spring:
<http-conf:conduit name="*.http-conduit">
<http-conf:tlsClientParameters useHttpsURLConnectionDefaultSslSocketFactory="true"/>
</http-conf:conduit>
глядя на то, как CXF и WAS работают, довольно просто получить доступ к Websphere SSLSocketFactory
и передайте его в CXF с помощью исходящего перехватчика.
если вы используете следующий класс:
public class WebsphereSslOutInterceptor extends AbstractPhaseInterceptor<Message> {
private String sslAlias = null;
public WebsphereSslOutInterceptor() {
super(Phase.SETUP);
}
public void handleMessage(Message message) throws Fault {
Conduit conduit = message.getExchange().getConduit(message);
if (conduit instanceof HTTPConduit) {
HTTPConduit httpConduit = (HTTPConduit)conduit;
String endpoint = (String) message.get(Message.ENDPOINT_ADDRESS);
if (endpoint != null) {
try {
URL endpointUrl = new URL(endpoint);
Map<String, String> connectionInfo = new HashMap<String, String>();
connectionInfo.put(
JSSEHelper.CONNECTION_INFO_REMOTE_HOST,
endpointUrl.getHost());
connectionInfo.put(
JSSEHelper.CONNECTION_INFO_REMOTE_PORT,
Integer.toString(endpointUrl.getPort()));
connectionInfo.put(
JSSEHelper.CONNECTION_INFO_DIRECTION,
JSSEHelper.DIRECTION_OUTBOUND);
SSLSocketFactory factory =
JSSEHelper.getInstance().getSSLSocketFactory(
sslAlias,
connectionInfo,
null);
TLSClientParameters tlsClientParameters = httpConduit.getTlsClientParameters();
if (tlsClientParameters != null) {
tlsClientParameters.setSSLSocketFactory(factory);
}
} catch (MalformedURLException e) {
throw new Fault(e);
} catch (SSLException e) {
throw new Fault(e);
}
}
}
}
public void setSslAlias(String sslAlias) {
this.sslAlias = sslAlias;
}
}
затем вы сможете подключиться к SSLSocketFactory Websphere и при необходимости использовать параметры "конфигурация SSL динамической исходящей конечной точки" для указания любых клиентских сертификатов, указав перехватчик в jaxws:client
tag:
<jaxws:client id="proxyName"
serviceClass="proxyClass"
address="${web.service.endpointaddress}">
<jaxws:outInterceptors>
<bean class="my.pkg.WebsphereSslOutInterceptor" />
</jaxws:outInterceptors>
</jaxws:client>
в сторону, если sslAlias
свойство объявляется в WebsphereSslOutInterceptor
клиентский сертификат может быть выбран на основе его псевдонима.
потому что это с помощью SSLSocketFactory
из Websphere хранилища доверия также будут использоваться из Websphere.
EDIT:
я использовал CXF 2.3.6 и Websphere 6.1
решение beny23 отлично работает для меня на WAS7 со следующими изменениями (причина: httpConduit.getTlsClientParameters () может иметь значение null):
заменить эту часть:
TLSClientParameters tlsClientParameters = httpConduit.getTlsClientParameters();
if (tlsClientParameters != null) {
tlsClientParameters.setSSLSocketFactory(factory);
}
С этого:
TLSClientParameters tlsClientParameters = httpConduit.getTlsClientParameters();
if (tlsClientParameters == null) {
tlsClientParameters = new TLSClientParameters();
httpConduit.setTlsClientParameters(tlsClientParameters);
}
tlsClientParameters.setSSLSocketFactory(factory);