SQL注入和SCRIPT注入,是一个烦人的东西,那么这个问题该怎么解决呢?下面就说一说如何解决这个问题。
在项目一开始,如果就考虑到这个问题的话,那是可以完全避免的。
反script注入:在jsp页面中解决,增删查修审都用struts标签 ,是没有任何问题的。如果是html标签的话,用jstl标签也可以完全解决。
那么如果用到文本编辑器的时候,又该怎么解决啊?我的反SCRIPT注入就可以解决这个问题了。
反sql注入:如果是jdbc的话,不要用Statement,用PreparedStatement就可以避免。如果用hibernate的话,用 Criteria查询就可以解决这个问题。
如何是在项目快完结的时候才发现这个问题,那该怎么解决啊?
apache提供了工具类:org.apache.commons.lang.StringEscapeUtils,它里面有对应的方法解决这个问题。
下面是我自己提供一种方法。
为了实现反SQL注入和反SCRIPT注入,本例应用反射技术和责任链模式实现了这个功能。它对于系统来说是可插拨的,这样就实现了与系统的松散耦合。
它的主要思想是:把Form对象,PO对象以及VO等对象中的String型属性的值或者String类型的参数进行过滤后重新封装为原有类型的对象。在获取对象的时候应用了 java反映技术,
在进行过滤的时候,实现了链式过滤。这样做,就是为了达到可维护性,可扩展性,可重用性以及灵活性的目的。
以下是源代码:
package net.better_best.www.utils.filter;
public class Request {
// 存储需要过滤的字符串
private String requestStr;
public String getRequestStr() {
return requestStr;
}
public void setRequestStr(String requestStr) {
this.requestStr = requestStr;
}
}
package net.better_best.www.utils.filter;
public class FilterConstant {
//定义sql过滤的内容
public static String[][] SQL_FILTER = {
{";",""},
{"'","''"},
{"--",""},
{"%",""}
};
//定义script过滤的内容
public static String[][] SCRIPT_FILTER = {
{"(<[i|I][n|N][p|P][u|U][t|T])([^>]*)(/>)",""},
{"(<[i|I][n|N][p|P][u|U][t|T])([\\s\\S]*)(</[i|I][n|N][p|P][u|U][t|T]>)",""},
{"(<[t|T][a|A][b|B][l|L][e|E])([^>]*)(/>)",""},
{"(<[t|T][a|A][b|B][l|L][e|E])([\\s\\S]*)(</[t|T][a|A][b|B][l|L][e|E]>)",""},
{"(<[d|D][i|I][v|V])([^>]*)(/>)",""},
{"(<[d|D][i|I][v|V])([\\s\\S]*)(</[d|D][i|I][v|V]>)",""},
{"(<[b|B][u|U][t|T][t|T][o|O][n|N])([^>]*)(/>)",""},
{"(<[b|B][u|U][t|T][t|T][o|O][n|N])([\\s\\S]*)(</[b|B][u|U][t|T][t|T][o|O][n|N]>)",""},
{"(<[s|S][c|C][r|R][i|I][p|P][t|T])([^>]*)(/>)",""},
{"(<[s|S][c|C][r|R][i|I][p|P][t|T])([\\s\\S]*)(</[s|S][c|C][r|R][i|I][p|P][t|T])(>)",""},
};
}
package net.better_best.www.utils.filter;
public interface IFilter {
void doFilter(Request request, FilterChain chain);
}
package net.better_best.www.utils.filter;
public class SqlFilter implements IFilter {
@Override
//进行sql过滤
public void doFilter(Request request, FilterChain chain) {
if (request != null) {
String strRequest = request.getRequestStr();
String[][] sqlFilter = FilterConstant.SQL_FILTER;
for (String[] strings : sqlFilter) {
strRequest = strRequest.replace(strings[0], strings[1]);
}
request.setRequestStr(strRequest);
}
chain.doFilter(request, chain);
}
}
package net.better_best.www.utils.filter;
public class ScriptFilter implements IFilter {
@Override
//进行script过滤
public void doFilter(Request request, FilterChain chain) {
if (request != null) {
String strRequest = request.getRequestStr();
String[][] scriptFilter = FilterConstant.SCRIPT_FILTER;
for (String[] strings : scriptFilter) {
strRequest = strRequest.replaceAll(strings[0], strings[1]);
}
request.setRequestStr(strRequest);
}
chain.doFilter(request, chain);
}
}
package net.better_best.www.utils.filter;
public enum FilterType {
SQL_TYPE,SCRIPT_TYPE ;
}
package net.better_best.www.utils.filter;
public class FilterHelper {
/*
* 生成过滤链条 参数:String type:过滤类型 返回:FilterChain; 根据过滤类型产生过滤链条
*/
public static FilterChain createFilterChain(FilterType type,FilterChain fChain) throws Exception {
if (type == null)
return null;
else if (type.equals(FilterType.SQL_TYPE))
return fChain.addFilter(new SqlFilter());
else if (type.equals(FilterType.SCRIPT_TYPE))
return fChain.addFilter(new ScriptFilter());
else
return null;
}
/*
* 把要过滤的字符串封装成Request对象
*/
public static Request init(String str) throws Exception {
if (str == null || str == "")
return null;
Request request = new Request();
request.setRequestStr(str);
return request;
}
/*
* 对Request对象进行循环过滤
*/
public static String result(Request request, FilterChain fChain)
throws Exception {
if (request == null || fChain == null || fChain.size() == 0)
return null;
fChain.doFilter(request, fChain);
return request.getRequestStr();
}
}
package net.better_best.www.utils.filter;
import java.util.ArrayList;
import java.util.List;
public class FilterChain implements IFilter {
// 使用 List 保存过滤器
private List<IFilter> filters = new ArrayList<IFilter>();
private int index = 0;
// 用于添加过滤器,可以添加实现了IFilter接口的FilterChain
public FilterChain addFilter(IFilter f) {
this.filters.add(f);
return this;
}
@Override
public void doFilter(Request request, FilterChain chain) {
// 判断是否是否遍历到 List 的最大值,如果是 return
if (index == filters.size())
return;
// 逐一获取过滤器
IFilter f = filters.get(index);
// 此过滤器链的下标,是遍历过滤器的索引
index++;
// 使用列表中的第index个过滤器,将更改后的 request ,chain 传进去,
f.doFilter(request,chain);
index = 0;
}
public int size(){
return filters.size();
}
}
package net.better_best.www.utils;
import java.lang.reflect.Field;
import net.better_best.www.utils.filter.FilterChain;
import net.better_best.www.utils.filter.FilterHelper;
import net.better_best.www.utils.filter.FilterType;
public class Filter {
/*
* 参数:Object,接收ActionForm,Plain Object,View.Object的属性值应为单值类型,不能为复合类型或数组类型;
* 参数:FilterType,定义需要过滤的类型; 返回值:Object; 作用:根据已定义的过滤规则,过滤所传入Object值;
*/
public static Object objectFilter(Object obj, FilterType... types) {
if (obj == null)return obj;
Class clazz = obj.getClass();
if (clazz.isArray() || clazz.isInterface() || clazz.isPrimitive())return obj;
Field[] fds = clazz.getDeclaredFields();
for (Field field : fds) {
if (field.getType().getName().equals("java.lang.String")) {
field.setAccessible(true);
Object before = null;
try {
before = field.get(obj);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if (before != null)
try {
field.set(obj, doFilter(before.toString(), types));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return obj;
}
/*
* 按照定义好的过滤规则,进行过滤; 参数:String str ,待过滤字符串 返回:String; 已过滤字符串
*/
public static String doFilter(String str, FilterType... types) {
if (str == null || str == "")
return null;
FilterChain fChain = new FilterChain();
String result = "";
try {
if (types.length == 0) {
FilterType[] filterTypes = FilterType.values();
for (FilterType filterType : filterTypes) {
fChain = FilterHelper.createFilterChain(filterType, fChain);
}
} else {
for (FilterType type : types) {
fChain = FilterHelper.createFilterChain(type, fChain);
}
}
if (fChain == null) {
result = str;
} else {
result = FilterHelper.result(FilterHelper.init(str), fChain);
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
使用方法:调用Filter的两个方法,就可以了。
以上内容为全部代码;
欢迎对本文的内容提出不同见解和质疑,不胜感激。
如果疑问,可发邮件联系我。可发邮件索取源代码。