cxf+spring開發(二)--- Ip地址攔截器,限制客戶端Ip地址,只允許資料庫中已經配置的Ip地址
阿新 • • 發佈:2019-02-20
上上篇博文中介紹瞭如何搭建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>