我们已经使用Springs HttpInvoker几个星期了,它就像一个魅力。从我的前端(web)应用程序,我连接到后端的userService,如下所示:
<bean id="userService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<property name="serviceUrl" value="http://${backend.host}/backend-ws/remoting/UserService"/>
<property name="serviceInterface" value="com...service.UserService"/>
</bean>
然后很好地将UserService注入我们的前端类。
现在我们在适当的(WAS7)服务器上部署它,并且要求使用SSL(https)。所以,我将http(serviceUrl的)更改为https,但后来我得到了:
org.springframework.remoting.RemoteAccessException: Could not access HTTP invoker remote service at [https://pbp-dev.dev.echonet/public/backend-ws/remoting/ParameterHelper]; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
这是有道理的,因为服务器上安装的证书(WAS运行的地方)未由CA签名。
我们已经有了一些经验,因为在同一个WAS上有一个web服务正在运行;为此,我们使用cxf并生成了一个驻留在客户端应用程序中的jks文件(带有keytool),其设置如下:
<http:conduit name="https://serverurl/.*">
<http:tlsClientParameters secureSocketProtocol="SSL" disableCNCheck="false">
<sec:trustManagers>
<sec:keyStore type="jks" password="pass123" resource="trust.jks"/>
</sec:trustManagers>
</http:tlsClientParameters>
我想Http Invoker我们需要做类似的事情,但我们不知道如何在调用者中使用这个trust.jks。
我找到的一件事是使用不同的requestExecutor;像这样:
<bean id="userService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<property name="serviceUrl" value="https://${backend.host}/backend-ws/remoting/UserService"/>
<property name="serviceInterface" value="com...service.UserService"/>
<property name="httpInvokerRequestExecutor">
<bean class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor" />
</property>
</bean>
在此之后我不再收到证书错误,但从那时起我似乎没有创建userService:
NoSuchBeanDefinitionException: No matching bean of type [com...service.UserService] found for dependency
答案 0 :(得分:2)
如果你混合你可以在这里找到的(http://stackoverflow.com/questions/5947162/https-and-self-signed-certificate-issue)来配置返回的HttpClient有一个预配置的SSLSocketFactory,你可以更改套接字工厂的主机名验证程序以接受证书,接近这个:
xxx.setHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) { println("bypassing ssl cert handshaking as configured for self signed cert."); return true; }
});
根据您的配置,除了使用CommonsHttpInvokerRequestExecutor之外,您还必须配置使用的HTTPClient和SSL套接字工厂
我知道这可能不会完全回答你的问题,但它是其他搜索的起点!祝你好运,不要忘记发布最终解决方案。
答案 1 :(得分:1)
您可以尝试以下内容:
首先编写自定义类org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor
:
package com.myorg.proid.sample;
import static org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.X509Certificate;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor;
/**
* @author visruth
*
*/
public class CustomHttpComponentsHttpInvokerRequestExecutor extends
HttpComponentsHttpInvokerRequestExecutor {
public CustomHttpComponentsHttpInvokerRequestExecutor() {
skipSecurityChecking();
}
@SuppressWarnings("deprecation")
private void skipSecurityChecking() {
// HttpClient from super class.
HttpClient httpClient = getHttpClient();
TrustStrategy trustStrategy = new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] certificate,
String authType) {
return true;
}
};
try {
httpClient
.getConnectionManager()
.getSchemeRegistry()
.register(
new Scheme("https", 80, new SSLSocketFactory(
trustStrategy,
ALLOW_ALL_HOSTNAME_VERIFIER)));
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
}
}
并在 xml 文件中引用此类,而不是org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor
<bean id="userService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<property name="serviceUrl" value="https://${backend.host}/backend-ws/remoting/UserService"/>
<property name="serviceInterface" value="com...service.UserService"/>
<property name="httpInvokerRequestExecutor">
<bean class="com.myorg.proid.sample.CustomHttpComponentsHttpInvokerRequestExecutor" />
</property>
</bean>