【問題】 遇到内部管理非常嚴格的客戶可能存在一套内部系統的部署規範,例如隻支援HTTPS協定不支援HTTP,如果系統多出采用HttpInvoker,而此處的配置大多不能直接支援HTTPS。我們可以建議客戶同時開放HTTP和HTTPS,對外隻開放HTTPS端口,此時實體伺服器内部的應用可以使用HTTP協定進行HttpInvoker互動,但如果是分布式部署呢? 【解決辦法】 1. 大多的配置如下(很多程式都采用如下配置方式),此時隻能支援HTTP協定,不支援HTTPS: [java] view plain copy print ?
- <bean id="remoteService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
- <!-- 遠端服務的url-->
- <property name="serviceUrl" value="${tt.server}/remoteService.remoting" />
- <!-- 遠端服務所實作的接口-->
- <property name="serviceInterface" value="org.kevin.SimpleService" />
- </bean>
<bean id="remoteService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<!-- 遠端服務的url-->
<property name="serviceUrl" value="${tt.server}/remoteService.remoting" />
<!-- 遠端服務所實作的接口-->
<property name="serviceInterface" value="org.kevin.SimpleService" />
</bean>
2. 可以調整為如下,使其同時支援HTTP和HTTPS: [java] view plain copy print ?
- <SPAN style="WHITE-SPACE: pre"> </SPAN><bean id="remoteService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
- <!-- 遠端服務的url-->
- <property name="serviceUrl" value="${tt.server}/remoteService.remoting" />
- <!-- 遠端服務所實作的接口-->
- <property name="serviceInterface" value="org.kevin.SimpleService" />
- <property name="httpInvokerRequestExecutor">
- <bean class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor"></bean>
- </property>
- </bean>
<bean id="remoteService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<!-- 遠端服務的url-->
<property name="serviceUrl" value="${tt.server}/remoteService.remoting" />
<!-- 遠端服務所實作的接口-->
<property name="serviceInterface" value="org.kevin.SimpleService" />
<property name="httpInvokerRequestExecutor">
<bean class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor"></bean>
</property>
</bean>
但問題是又來了,這個httpInvokerRequestExecutor使用的是HttpClient,而這個家夥要求你必須配置證書檔案(配置方法很複雜,還要考慮證書過期更新問題)。 3. 怎麼辦!?改寫一下CommonsHttpInvokerRequestExecutor ,讓他即支援HTTPS同時還不校驗證書(有點安全隐患,不過用該可以接收),于是采用如下配置: [java] view plain copy print ?
- <bean id="remoteService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
- <!-- 遠端服務的url-->
- <property name="serviceUrl" value="${tt.server}/remoteService.remoting" />
- <!-- 遠端服務所實作的接口-->
- <property name="serviceInterface" value="org.kevin.SimpleService" />
- <property name="httpInvokerRequestExecutor">
- <bean class="org.kevin.KevinCommonsHttpInvokerRequestExecutor"></bean>
- </property>
- </bean>
<bean id="remoteService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<!-- 遠端服務的url-->
<property name="serviceUrl" value="${tt.server}/remoteService.remoting" />
<!-- 遠端服務所實作的接口-->
<property name="serviceInterface" value="org.kevin.SimpleService" />
<property name="httpInvokerRequestExecutor">
<bean class="org.kevin.KevinCommonsHttpInvokerRequestExecutor"></bean>
</property>
</bean>
【示例代碼】 [java] view plain copy print ?
- package org.kevin;
- import java.io.IOException;
- import java.net.InetAddress;
- import java.net.Socket;
- import java.net.UnknownHostException;
- import java.security.cert.CertificateException;
- import java.security.cert.X509Certificate;
- import javax.net.ssl.SSLContext;
- import javax.net.ssl.TrustManager;
- import javax.net.ssl.X509TrustManager;
- import org.apache.commons.httpclient.ConnectTimeoutException;
- import org.apache.commons.httpclient.HttpClientError;
- import org.apache.commons.httpclient.params.HttpConnectionParams;
- import org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory;
- import org.apache.commons.httpclient.protocol.Protocol;
- import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
- import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
- import org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor;
- public class KevinCommonsHttpInvokerRequestExecutor extends CommonsHttpInvokerRequestExecutor {
- static {
- ProtocolSocketFactory fcty = new MySecureProtocolSocketFactory();
- Protocol.registerProtocol("https", new Protocol("https", fcty, 443));
- }
- }
- class MyX509TrustManager implements X509TrustManager {
- public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
- }
- public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
- }
- public X509Certificate[] getAcceptedIssuers() {
- return null;
- }
- public boolean isClientTrusted(X509Certificate[] arg0) {
- return false;
- }
- public boolean isServerTrusted(X509Certificate[] arg0) {
- return false;
- }
- }
- class MySecureProtocolSocketFactory implements SecureProtocolSocketFactory {
- private SSLContext sslContext = null;
- public MySecureProtocolSocketFactory() {
- }
- private static SSLContext createEasySSLContext() {
- try {
- SSLContext context = SSLContext.getInstance("SSL");
- context.init(null, new TrustManager[] { new MyX509TrustManager() }, null);
- return context;
- } catch (Exception e) {
- throw new HttpClientError(e.toString());
- }
- }
- private SSLContext getSSLContext() {
- if (this.sslContext == null) {
- this.sslContext = createEasySSLContext();
- }
- return this.sslContext;
- }
- public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException,
- UnknownHostException {
- return getSSLContext().getSocketFactory().createSocket(host, port, clientHost, clientPort);
- }
- public Socket createSocket(final String host, final int port, final InetAddress localAddress, final int localPort,
- final HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
- if (params == null) {
- throw new IllegalArgumentException("Parameters may not be null");
- }
- int timeout = params.getConnectionTimeout();
- if (timeout == 0) {
- return createSocket(host, port, localAddress, localPort);
- } else {
- return ControllerThreadSocketFactory.createSocket(this, host, port, localAddress, localPort, timeout);
- }
- }
- public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
- return getSSLContext().getSocketFactory().createSocket(host, port);
- }
- public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException,
- UnknownHostException {
- return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose);
- }
- }
package org.kevin;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.HttpClientError;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
import org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor;
/**
* <p>
* Title: HttpInvoker的自定義httpInvokerRequestExecutor實作
* </p>
*
* <p>
* Description: 支援HTTP和HTTPS,同時HTTPS不進行證書的校驗
* </p>
*
* <p>
* Company: 北京九恒星科技股份有限公司
* </p>
*
* @author li.wenkai
*
* @since:2011-10-18 下午03:37:03
*
*/
public class KevinCommonsHttpInvokerRequestExecutor extends CommonsHttpInvokerRequestExecutor {
static {
ProtocolSocketFactory fcty = new MySecureProtocolSocketFactory();
Protocol.registerProtocol("https", new Protocol("https", fcty, 443));
}
}
class MyX509TrustManager implements X509TrustManager {
/*
* (non-Javadoc)
*
* @see
* javax.net.ssl.X509TrustManager#checkClientTrusted(java.security.cert.
* X509Certificate[], java.lang.String)
*/
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
}
/*
* (non-Javadoc)
*
* @see
* javax.net.ssl.X509TrustManager#checkServerTrusted(java.security.cert.
* X509Certificate[], java.lang.String)
*/
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
}
/*
* (non-Javadoc)
*
* @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
*/
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isClientTrusted(X509Certificate[] arg0) {
return false;
}
public boolean isServerTrusted(X509Certificate[] arg0) {
return false;
}
}
class MySecureProtocolSocketFactory implements SecureProtocolSocketFactory {
private SSLContext sslContext = null;
/**
* Constructor for MySecureProtocolSocketFactory.
*/
public MySecureProtocolSocketFactory() {
}
/**
*
* @return
*/
private static SSLContext createEasySSLContext() {
try {
SSLContext context = SSLContext.getInstance("SSL");
context.init(null, new TrustManager[] { new MyX509TrustManager() }, null);
return context;
} catch (Exception e) {
throw new HttpClientError(e.toString());
}
}
/**
*
* @return
*/
private SSLContext getSSLContext() {
if (this.sslContext == null) {
this.sslContext = createEasySSLContext();
}
return this.sslContext;
}
/*
* (non-Javadoc)
*
* @see
* org.apache.commons.httpclient.protocol.ProtocolSocketFactory#createSocket
* (java.lang.String, int, java.net.InetAddress, int)
*/
public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException,
UnknownHostException {
return getSSLContext().getSocketFactory().createSocket(host, port, clientHost, clientPort);
}
/*
* (non-Javadoc)
*
* @see
* org.apache.commons.httpclient.protocol.ProtocolSocketFactory#createSocket
* (java.lang.String, int, java.net.InetAddress, int,
* org.apache.commons.httpclient.params.HttpConnectionParams)
*/
public Socket createSocket(final String host, final int port, final InetAddress localAddress, final int localPort,
final HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
if (params == null) {
throw new IllegalArgumentException("Parameters may not be null");
}
int timeout = params.getConnectionTimeout();
if (timeout == 0) {
return createSocket(host, port, localAddress, localPort);
} else {
return ControllerThreadSocketFactory.createSocket(this, host, port, localAddress, localPort, timeout);
}
}
/*
* (non-Javadoc)
*
* @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
*/
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return getSSLContext().getSocketFactory().createSocket(host, port);
}
/*
* (non-Javadoc)
*
* @see
* SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String
* ,int,boolean)
*/
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException,
UnknownHostException {
return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose);
}
}