public class BugFilter implements Filter {
private static Logger logger = Logger.getLogger(BugFilter.class);
//定义存放非法参数属性文件的值集合
private static List<String> list = new ArrayList<String>();
//程序加载时执行且仅执行一次读取属性文件内容
static{
Properties prop = new Properties();
try {
//加载属性文件
prop.load(BugFilter.class.getResourceAsStream("/conf/param.properties"));
//读取属性文件的键集合
Set<String> set = prop.stringPropertyNames();
for(String str : set) {
//获取每个属性的值
String param = prop.getProperty(str);
list.add(param);
}
} catch (IOException e) {
e.printStackTrace();
logger.debug("加载属性文件param.properties时出错!");
}
}
public BugFilter() {
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
Map map=request.getParameterMap();
HttpServletRequest req=(HttpServletRequest)request;
HttpServletResponse rs=(HttpServletResponse)response;
//logger.debug("BugFilter---"+map.size());
//add by liushuang start 添加客户端请求信息
//logger.info("------客户端ip:"+((HttpServletRequest)request).getRemoteAddr());
//logger.info("------客户端端口号:"+((HttpServletRequest)request).getRemotePort());
//logger.info("------请求详细地址及参数:"+((HttpServletRequest)request).getRequestURI()+"?"+((HttpServletRequest)request).getQueryString());
//add by liushuang end
if(isInvalidParams(map.values().toArray()) || isInvalidParams(map.keySet().toArray()) || isInvalidParams(new Object[]{req.getRequestURL().toString(),req.getQueryString()})){
logger.error("BugFilter error 存在非法请求---");
logger.error("------客户端ip:"+((HttpServletRequest)request).getRemoteAddr());
logger.error("------客户端端口号:"+((HttpServletRequest)request).getRemotePort());
logger.error("------请求详细地址及参数:"+((HttpServletRequest)request).getRequestURI()+"?"+((HttpServletRequest)request).getQueryString());
rs.reset();
rs.sendRedirect(req.getContextPath()+"/error.jsp");
}else{
chain.doFilter(request, response);
}
}
/**
* 检查params里的参数是否非法,非法则返回true
* @param params 被检查的参数,params数组可以为字符串数组,也可以为字符串数组的数组
* @return 当params里字符串含有非法字符串时返回true,否则返回false;
*/
public boolean isInvalidParams(Object[] params){
if(params.length == 0){
return false;
}
for (int i = 0; i < params.length; i++) {
if(params[i]!=null){
String[] value;
if (params[i] instanceof String[]) {
value = (String[]) params[i];
} else {
value = new String[]{(String) params[i]};
}
for (int j = 0; j < value.length; j++) {
if(containInvalidString(value[j])){
logger.error("发现非法参数------"+value[j]);
return true;
}
}
}
}
return false;
}
/**
* 检查是否包含非法字符
* @param content
* @return
*/
private boolean containInvalidString(String content) {
Pattern[] patterns = null;
String regex = "";
if(list.size() == 0){
return false;
}
//定义正则表达式的编译表示形式的数组
patterns = new Pattern[list.size()];
for (int j = 0; j < list.size(); j++) {
regex = (String) list.get(j);
if (!StringUtil.isEmpty(regex)) {
//将给定的正则表达式编译到具有给定标志的模式中。
//CASE_INSENSITIVE,启用不区分大小写的匹配。
patterns[j] = Pattern.compile(regex,
Pattern.CASE_INSENSITIVE);
}
}
for (int k = 0; k < patterns.length; k++) {
//创建匹配给定输入与此模式的匹配器。
Matcher m = patterns[k].matcher(content);
//尝试查找与该模式匹配的输入序列的下一个子序列。
if (m.find()) {
return true;
}
}
return false;
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
非法字符实例:
#illegal param list
param.1=<\\\\s*script[^>]*>.*<\\\\s*/\\\\s*script[^>]*>
param.2=<.*script[^>]*>.*<.*script[^>]*>
param.3=<.*script[^>]*>
param.4=<.*embed[^>]*>
param.5=<.*object[^>]*>
param.6=<.*layer[^>]*>
param.7=<.*style[^>]*>
param.8=<.*meta[^>]*>
param.9=<.*iframe[^>]*>
param.10=<.*frame[^>]*>
param.11=<.*link[^>]*>
param.12=<.*import[^>]*>
param.13=<.*xml[^>]*>
param.14=<.*href[^>]*>
param.15=<.*input[^>]*>
param.16=<.*url[^>]*>
param.17=<.*input[^>]*>
param.18=<.*javascript[^>]*>
param.19=<.*vbscript[^>]*>
param.20=<.*expression[^>]*>
param.21=<.*tr[^>]*>
param.22=<.*td[^>]*>
param.23=<.*html[^>]*>
param.24=(<style[^>]*>[^>]+)(expression|javascript|vbscript|-moz-binding)(.*</style[^>]*>)
param.25=(<[^>]*)AllowScriptAccess([^>]*>)
param.26=drop\\\\s+table|xp_cmdshell|netlocalgroup\\\\s+administrators|net\\\\s+user|""|((insert|delete|update|truncate|exec)\\\\s+)
param.27=%00
param.28=<\\\\s*a\\\\s+[^>]*href[^>]*http\\\://
param.29=(<[^>]*)(javascript|vbscript|livescript|ms-its|mhtml|data|firefoxurl|mocha):([^>]*>)
param.30=(<[^>]*style=[^>]+)(expression|javascript|vbscript|-moz-binding)([^>]*>)
param.31=(<[^>]*style\\\=.*)/\\\\*.*\\\\*/([^>]*>)
param.32=(<style[^>]*>.*)/\\\\*.*\\\\*/(.*</style[^>]*>)
param.33=onmouseover\\\\s*\\\=|onmouseout\\\\s*\\\=|onmousedown\\\\s*\\\=|onmouseup\\\\s*\\\=|onmousemove\\\\s*\\\=|onclick\\\\s*\\\=|ondblclick\\\\s*\\\=|onkeypress\\\\s*\\\=|onkeydown\\\\s*\\\=|onkeyup\\\\s*\\\=|ondragstart\\\\s*\\\=|onerrorupdate\\\\s*\\\=|onhelp\\\\s*\\\=|onreadystatechange\\\\s*\\\=|onrowenter\\\\s*\\\=|onrowexit\\\\s*\\\=|onselectstart\\\\s*\\\=|onload\\\\s*\\\=|onunload\\\\s*\\\=|onbeforeunload\\\\s*\\\=|onblur\\\\s*\\\=|onerror\\\\s*\\\=|onfocus\\\\s*\\\=|onresize\\\\s*\\\=|onscroll\\\\s*\\\=|oncontextmenu\\\\s*\\\=|ACUstart|ACUend|cmdshell|truncate|alert|confirm|prompt
param.34=.*getWriter.*
param.35=.*FileOutputStream.*
param.36=.*getRuntime.*
param.37=.*getRequest.*
param.38=.*getProperty.*
param.39=.*\\\\\\\\u0023.*
param.40=.*\\\\\\\\43.*
#param.41=.*\\*.*
#param.42=.*\\\:.*
param.43=.*'.*
#param.44=.*\\".*
#param.45=.*,.*
param.46=.*<.*
#param.47=.*>.*
#param.48=.*;.*
#param.49=.*add.*
param.50=.*exec.*
#param.51=.*insert.*
#param.52=.*select.*
#param.53=.*delete.*
#param.54=.*update.*
#param.55=.*count.*
param.56=.*chr.*
#param.57=.*mid.*
param.58=.*master.*
param.59=.*truncate.*
param.60=.*char.*
param.61=.*declare.*