首页 > 代码库 > CXF 的IP拦截

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限制了