现在的位置: 首页 > 综合 > 正文

HttpInvoker支持不需要证书的HTTPS

2018年08月07日 ⁄ 综合 ⁄ 共 5750字 ⁄ 字号 评论关闭
【问题】
遇到内部管理非常严格的客户可能存在一套内部系统的部署规范,例如只支持HTTPS协议不支持HTTP,如果系统多出采用HttpInvoker,而此处的配置大多不能直接支持HTTPS。我们可以建议客户同时开放HTTP和HTTPS,对外只开放HTTPS端口,此时物理服务器内部的应用可以使用HTTP协议进行HttpInvoker交互,但如果是分布式部署呢?
 
   【解决办法】
1.  大多的配置如下(很多程序都采用如下配置方式),此时只能支持HTTP协议,不支持HTTPS:
<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:           
		<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同时还不校验证书(有点安全隐患,不过用该可以接收),于是采用如下配置:
   <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>

【示例代码】

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);
	}
}

 

抱歉!评论已关闭.