/*
* Created on 2004-12-2
*wap應用對請求地址的限制 filter,也可以用於其他
*
*/
package org.nightkids.filter.wap;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* @author weidewang
*/
public class BlockNotMobileAccess implements Filter {
private Log _logger = LogFactory.getLog(this.getClass());
private static final String MODE_SESSION_IP = "BlockNotMobileAccessModeSession";
private static FilterConfig filterConfig;
private HttpServletRequest request;
private HttpServletResponse response;
private HttpSession session;
private static Properties gatewayProperties = new Properties();
private static List gatewayList = new ArrayList();
public void init(FilterConfig fconfig) throws ServletException {
filterConfig = fconfig;
initGatewayList(filterConfig);
}
/**
* 加載網關列表
*
* @param fc
*/
private void initGatewayList(FilterConfig fc) {
String properRealPath = fc.getServletContext().getRealPath(fc.getInitParameter("gateway-properties"));
try {
gatewayProperties.load(new FileInputStream(properRealPath));
_logger.debug("已經讀取全國網關列表配置文件: " + properRealPath);
Enumeration elems = gatewayProperties.elements();
while (elems.hasMoreElements()) {
String gateway = (String) elems.nextElement();
// 如果 gateway 裏面沒有 - 的話 就是一個單一的 IP ,直接加到 list 中,否則 獲取 - 左邊到 . 的,- 右邊到 結束的 字符串,轉爲數字,然後遍歷一下爲單一的 ip 加入 list 中
int indexOf = gateway.indexOf("-");
if (indexOf == -1) {// 如果是單一ip,直接加到 list 中
gatewayList.add(gateway);
_logger.debug("添加一個網關: " + gateway);
} else {
// 否則是一個 ip 組,現在只解析最後一段 ip 組
// 首先獲取到 - 左邊 第一個 . 到開始的字符串
int indexLeftPoint = gateway.lastIndexOf(".", indexOf) + 1;// 獲取 - 左邊到 . 的 字符串
String prefixStr = gateway.substring(0, indexLeftPoint);// 獲取到 - 左邊 第一個 . 到開始的字符串
String leftStr = gateway.substring(indexLeftPoint, indexOf).trim();// 得到左邊的字符串
String rightStr = gateway.substring(indexOf + 1).trim();// 獲取 - 右邊到結束的 字符串
// 已經得到字符串之後,就要遍歷一下分割成單獨的 ip 加入到 list 中
int leftInt = Integer.parseInt(leftStr);
int rightInt = Integer.parseInt(rightStr);
for (int i = leftInt; i <= rightInt; i++) {
String grGateway = prefixStr + i;
gatewayList.add(grGateway);
_logger.debug("添加一個網關: " + grGateway);
}
}
}
_logger.debug("共添加了 " + gatewayList.size() + " 個網關.");
} catch (NullPointerException e) {
_logger.debug("讀取全國網關列表配置文件錯誤:(沒有設置 gateway-properties) " + e);
} catch (FileNotFoundException e) {
_logger.debug("讀取全國網關列表配置文件錯誤:(找不到配置文件):" + properRealPath + " " + e);
} catch (IOException e) {
_logger.debug("讀取全國網關列表配置文件錯誤:(IO錯誤):" + properRealPath + " " + e);
}
}
/**
*
*/
public void doFilter(ServletRequest _servletRequest, ServletResponse _servletResponse, FilterChain filterChain) throws IOException, ServletException {
boolean isActive = false;
boolean allowAccess = false;
request = (HttpServletRequest) _servletRequest;
response = (HttpServletResponse) _servletResponse;
session = request.getSession(true);
if (null != filterConfig.getInitParameter("active")) {
if ("true".equalsIgnoreCase(filterConfig.getInitParameter("active")) || "yes".equalsIgnoreCase(filterConfig.getInitParameter("active"))) {
isActive = true;
_logger.debug("激活 " + this.getClass().getName());
}
}
if (isActive) {
allowAccess = doProcess(request);
} else {
allowAccess = true;
}
if (!allowAccess) {
error();
return;
}
filterChain.doFilter(_servletRequest, _servletResponse);
}
/**
* @param req
* @return true 通過,false 不能通過
*/
private boolean doProcess(HttpServletRequest req) {
String userAgent = null;
boolean bRe = true;
/**
* 設置調試模式
*/
String modeName = filterConfig.getInitParameter("mode-name");
String modeValue = filterConfig.getInitParameter("mode-value");
if (modeName != null && modeValue != null) {
if (request.getParameter(modeName) != null && modeValue.equals(request.getParameter(modeName)) || modeValue.equals(session.getAttribute(MODE_SESSION_IP))) {
session.setAttribute(MODE_SESSION_IP, modeValue);
return bRe;
}
}
/*
* 首先判斷瀏覽器類型
*/
String[] blockUserAgent = {
"Mozilla", "ApacheBench"
};
userAgent = req.getHeader("User-Agent").toLowerCase();
int indexOf = userAgent.indexOf("/");
if (indexOf == -1) {
indexOf = userAgent.indexOf("*");
if (indexOf == -1) {
indexOf = userAgent.length();
}
}
userAgent = userAgent.substring(0, indexOf);
for (int i = 0; i < blockUserAgent.length; i++) {
String str = blockUserAgent[i].toLowerCase();
if (str.equalsIgnoreCase(userAgent)) {
return false;
}
}
String getRemoteAddr = request.getRemoteAddr();
if (!gatewayList.contains(getRemoteAddr)) {// 如果網關列表裏沒有訪問者ip 的話,不允許訪問
return false;
}
return bRe;
}
public void destroy() {
}
private void error() throws IOException {
response.setContentType(filterConfig.getInitParameter("content-type"));
StringBuffer sb = new StringBuffer();
String errorMessage = "對不起,請使用手機訪問.";
if (filterConfig.getInitParameter("ERROR_MESSAGE") != null) {
errorMessage = filterConfig.getInitParameter("ERROR_MESSAGE");
}
sb.append("<!DOCTYPE wml PUBLIC /"-//WAPFORUM//DTD WML 1.1//EN/" /"http://www.wapforum.org/DTD/wml_1.1.xml/"><wml><card><p align=/"center/">" + errorMessage + "<br/><a href=/"http://wap.monternet.com//">夢網首頁</a></p></card></wml>");
Writer out = response.getWriter();
out.write(sb.toString());
out.close();
}
}