CXF 的IP攔截

很久沒有寫技術文檔了,今天 記錄下Webserver的Ip限制吧

需求是:webserver接口能在內網訪問,但是測試平臺的webserver要可以在外網訪問,這樣就有了一點區別,

這個實現的比較簡單配置文件就一個白名單

#可用的IP
whiteList=a;b;

表示一個內網網段都可以訪問

用配置文件讀取

package com.onepiece.cxf.util;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.ResourceBundle;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 配置文件工具
 * 
 * @author JueYue
 * @date 2014年7月3日 下午5:06:35
 */
public class CxfInterceptorProperties {

	private static final Logger logger = LoggerFactory
			.getLogger(CxfInterceptorProperties.class);

	private static boolean isNotIntercept = false;

	private static List<String> whiteList;

	static {
		ResourceBundle bundle;
		try {
			bundle = ResourceBundle.getBundle("cxf-interceptor");
		} catch (Exception e) {
			logger.info("cxf-interceptor沒有配置配置文件,使用缺省配置");
			bundle = ResourceBundle
					.getBundle("com/onepiece/cxf/util/cxf-interceptor");
		}
		whiteList = Arrays.asList(bundle.getString("whiteList").split(";"));
		try {
            Enumeration<NetworkInterface> netInterfaces = NetworkInterface
                    .getNetworkInterfaces();
            String ip;
            while (netInterfaces.hasMoreElements()) {
                NetworkInterface nif = netInterfaces.nextElement();
                Enumeration<InetAddress> iparray = nif.getInetAddresses();
                while (iparray.hasMoreElements()) {
                	ip = iparray.nextElement().getHostAddress();
                	if (ip.contains("192.168.0")) {
                		logger.info("發現測試IP地址,取消IP限制");
        				isNotIntercept = true;
        				break;
        			}
                	logger.debug("本機IP爲:{}",ip);
                }
            }
        } catch (Exception e) {
        	logger.info("獲取IP失敗,默認啓用攔截");
			e.printStackTrace();
        }
	}

	public static List<String> getWhiteList() {
		return whiteList;
	}

	public static boolean isNotIntercept() {
		return isNotIntercept;
	}

}

自己設置一個默認配置,但是測試平臺的話就沒有IP限制了,這裏獲取IP地址複雜點,因爲可能存在多個IP所以都獲取發現一下自己想要的IP地址

然後是IP攔截

package com.onepiece.cxf.address;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.transport.http.AbstractHTTPDestination;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.onepiece.cxf.util.CxfInterceptorProperties;

/**
 * 攔截配置文件的配置
 * 
 * @author JueYue
 * @date 2014年7月3日 下午5:05:46
 */
public class IpAddressInInterceptor extends AbstractPhaseInterceptor<Message> {

	private static final Logger logger = LoggerFactory
			.getLogger(IpAddressInInterceptor.class);

	public IpAddressInInterceptor() {
		super(Phase.RECEIVE);
	}

	public void handleMessage(Message message) throws Fault {
		HttpServletRequest request = (HttpServletRequest) message
				.get(AbstractHTTPDestination.HTTP_REQUEST);
		List<String> allowedList = CxfInterceptorProperties.getWhiteList();
		if (logger.isDebugEnabled() && request != null) {
			logger.debug("getRemoteAddr 獲取的IP:{},X-Client-Address 獲取的IP:{}",
					request.getRemoteAddr(),request.getHeader("X-Client-Address"));
		}
		if (CxfInterceptorProperties.isNotIntercept() || request == null) {
			return;
		}
		String ipAddress = getIP(request);
		// 處理白名單
		boolean contains = false;
		for (String allowIpAddress : allowedList) {
			if (ipAddress.startsWith(allowIpAddress)) {
				contains = true;
				break;
			}
		}
		if (!contains) {
			logger.warn("***********************發現一個外來IP,IP地址:" + ipAddress
					+ "**************");
			throw new Fault(new IllegalAccessException("IP address "
					+ ipAddress + " is not allowed"));
		}
	}

	private String getIP(HttpServletRequest request) {
		String IP = request.getHeader("X-Client-Address"); // 取客戶端IP地址
		if (StringUtils.isEmpty(IP)) {
			IP = request.getRemoteAddr();
		}
		return IP;
	}

}

這裏獲取IP首先是X-Clint-Address 因爲我們是用的PortTunnel代理的,這個設置下就可以在X-cliet-Address獲取真實IP

這樣我們就做到了IP限制.後面就是配置下

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:cxf="http://cxf.apache.org/core"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.0.xsd
	http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
	http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd"
	default-autowire="byName">

	<import resource="classpath:META-INF/cxf/cxf.xml" />
	<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
	<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
	
	<!-- IP地址輸入攔截器 -->  
	<bean id="ipAddressInInterceptor"  
   		class="com.onepiece.cxf.address.IpAddressInInterceptor" /> 
   	<!-- 全局Bus(輸入攔截器) -->  
   	<cxf:bus>
   		<cxf:inInterceptors>
   			<ref bean="ipAddressInInterceptor"/>
   		</cxf:inInterceptors>
   	</cxf:bus>
	
	
</beans>

使用的是全局設置,所以不用每個都配置,這裏需要注意一點default-lazy-init="true" 如果spring加上這個就會失效,

這裏基本就完成了IP限制了



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章