1. 程式人生 > >cxf+spring開發(二)--- Ip地址攔截器,限制客戶端Ip地址,只允許資料庫中已經配置的Ip地址

cxf+spring開發(二)--- Ip地址攔截器,限制客戶端Ip地址,只允許資料庫中已經配置的Ip地址

上上篇博文中介紹瞭如何搭建cxf和spring環境,本文將圍繞如何在此環境下編寫攔截器,只允許已經配置好的IP地址訪問伺服器端。

一、修改配置檔案applicationContext.xml

<span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
    xmlns:p="http://www.springframework.org/schema/p"  
    xmlns:jaxws="http://cxf.apache.org/jaxws"   
    xmlns:cxf="http://cxf.apache.org/core"  
    xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
    xsi:schemaLocation="http://www.springframework.org/schema/beans   
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd   
    http://cxf.apache.org/jaxws   
    http://cxf.apache.org/schemas/jaxws.xsd
    http://cxf.apache.org/transports/http/configuration
    http://cxf.apache.org/schemas/configuration/http-conf.xsd 
    http://cxf.apache.org/core 
    http://cxf.apache.org/schemas/core.xsd">  
      
    <import resource="classpath:META-INF/cxf/cxf.xml" />  
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />  
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />  
    
    <!-- WebService服務 --> 
    <bean id="inter" class="com.travelsky.cxfTest.AImpl"/>  

    <jaxws:endpoint id="cxfService" implementor="#inter" address="/CxfService" >
          <jaxws:inInterceptors>
            <ref bean="ipInIntercept"/>
        </jaxws:inInterceptors>
    </jaxws:endpoint>

    <!--毫秒單位 name 為 webservice 的域名 或者地址-->
    <http-conf:conduit name="${train.api.domain.name}.*">
        <http-conf:client ConnectionTimeout="10000" ReceiveTimeout="20000"/>
    </http-conf:conduit>

    <bean id="logIn" class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
    <bean id="logOut" class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
    
     <!-- 自定義攔截器-->
    <bean id="ipInIntercept" class="com.intercept.IpInIntercept"/>
  

    <!-- CXF 全域性的攔截器-->
   <cxf:bus>
       <cxf:inInterceptors>
           <ref bean="logIn"/>
       </cxf:inInterceptors>
       <cxf:outInterceptors>
           <ref bean="logOut" />
       </cxf:outInterceptors>
   </cxf:bus>

    
</beans>  </span>


在這個地方遇到一個標籤錯誤,錯誤提示

cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'jaxws:inInterceptors'.參見我的另一篇博文http://blog.csdn.net/yolanda_nuonuo/article/details/47016981

二、web.xml配置檔案

<span style="font-size:18px;"><span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>cxfTest</display-name>
 
   <context-param>  
        <param-name>contextConfigLocation</param-name>  
        <param-value>classpath:applicationContext.xml</param-value>  
    </context-param>
    
     <listener>  
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
    </listener>
    
    <listener>  
                  <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>  
    </listener>
    
    <!-- WebServices設定 -->
    <servlet>  
        <servlet-name>CxfService</servlet-name>  
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>  
        <load-on-startup>1</load-on-startup>  
    </servlet>  
      
    <servlet-mapping>  
        <servlet-name>CxfService</servlet-name>  
        <url-pattern>/*</url-pattern>  
    </servlet-mapping>  
 
    <welcome-file-list>  
        <welcome-file>index.jsp</welcome-file>  
    </welcome-file-list>
    
</web-app></span></span>

三、攔截器的編寫
<span style="font-size:18px;"><span style="font-size:18px;">

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

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;


/**
 * Ip攔截器
 *
 */
public class IpInIntercept extends AbstractPhaseInterceptor<Message>{

    private List<String> ipList = new ArrayList<String>();
    
    private final static Logger logger = LoggerFactory.getLogger(IpInIntercept.class);
    
    public IpInIntercept() {
        super(Phase.RECEIVE);
    }

    public void handleMessage(Message message) throws Fault {
        HttpServletRequest request = (HttpServletRequest) message.get(AbstractHTTPDestination.HTTP_REQUEST);
        String ipAddress = "";
        
        ConnOracle co = new ConnOracle();
        co.getConn();
        String sql = "select * from IPADDR";
        co.sqlExe(sql);
        
        boolean flag = false;
        int count = 0;
        
        if (null != request && count <= 10) {
            ipAddress = getUsrIPAddr(request);//獲取客戶端的IP地址
            logger.info("獲取到客戶端的IP地址是:" + ipAddress);
            System.out.println("獲取到客戶端的IP地址是:" + ipAddress);
            count++;
            
            for (String ipString : ipList) {
                if (ipString.equals(ipAddress)) {
                    flag = true;
                    break;
                }
            }
        }
        
        if (!flag) {  
            throw new Fault(new IllegalAccessException("IP address " + ipAddress + " is not allowed"));  
        }
        
    }
    
    /**
     * 獲取客戶端ip地址  
     * @param request
     * @return
     */
    public String getUsrIPAddr(HttpServletRequest request) {
        String ip = "";
        //1.首先考慮有反向代理的情況,如果有代理,通過“x-forwarded-for”獲取真實ip地址
        ip = request.getHeader("x-forwarded-for");
        //2.如果squid.conf的配製檔案forwarded_for項預設是off,則:X-Forwarded-For:unknown。考慮用Proxy-Client-IP或WL-Proxy-Client-IP獲取
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        //3.最後考慮沒有代理的情況,直接用request.getRemoteAddr()獲取ip
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        //4.如果通過多級反向代理,則可能產生多個ip,其中第一個非unknown的IP為客戶端真實IP(IP按照','分割)
        if(ip != null && ip.split(",").length > 1){
            ip = (ip.split(","))[0];
        }        
        //5.如果是伺服器本地訪問,需要根據網絡卡獲取本機真實ip
        if("127.0.0.1".equals(ip)) {
            try {
                ip = InetAddress.getLocalHost().getHostAddress();
            } catch (UnknownHostException e) {
                logger.error(e.getMessage(),e);//獲取伺服器(本地)ip資訊失敗
                return "";
            }
        }
//        6.校驗ip的合法性,不合法返回""
        if(!isValidIp(ip)) {
            return "The ip is invalid.";
        }else {
            return ip;
        }
//        return ip;
    }

    /**
     * 判斷是否為合法IP地址
     * @param ipAddress
     * @return
     */
    private boolean isValidIp(String ipAddress) {
        boolean retVal = false;
        try {
            if(ipAddress!=null && !"".equals(ipAddress)){
                Pattern pattern = Pattern.compile("([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}");
                retVal = pattern.matcher(ipAddress).matches();
            }            
        } catch(Exception e){
            logger.error(e.getMessage(), e);
        }
        return retVal;
    }

}</span></span>

三、資料庫工具類

由於使用了oracle資料庫,所以還要編寫資料庫工具類如下。

<span style="font-size:18px;"><span style="font-size:18px;">

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 資料庫連線
 *
 */
public class ConnOracle {
	//資料庫連線驅動
	public static final String driver = "oracle.jdbc.driver.OracleDriver";
	//資料庫連線地址
	public static final String url = "jdbc:oracle:thin:@172.25.2.148:1521:ORCL";
	//登入名
	public static final String usr = "twj";
	//密碼
	public static final String pwd = "123";
	//資料庫連線物件
	private Connection conn = null;
	//資料庫預編譯物件
	private PreparedStatement ps = null;
	//結果集
	private ResultSet rs = null;
	//結果字串
	private List<String> list = new ArrayList<String>();
	
	/**
	 * 獲取資料庫連線
	 * @return conn
	 */
	public Connection getConn() {
		try {
			Class.forName(driver);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		try {
			conn = DriverManager.getConnection(url, usr, pwd);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return conn;
	}
	
	/**
	 * 關閉所有資源
	 */
	public void closeAll()
	{
		if (ps != null) {
			try {
				ps.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}//if
		
	}
	
	/**
	 * 執行sql語句
	 * @param sqlString
	 */
	public List<String> sqlExe(String sqlString)
	{
		try {
			ps = conn.prepareStatement(sqlString);
			rs = ps.executeQuery();
			while (rs.next()) {
				list.add(rs.getString(2));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return list;
	}

}
</span></span>