/*
* 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();
}
}