SQL注入攻击能得逞是因为在原有SQL语句中加入了新的逻辑
比如:原sql="select * from user where userid='"+userid+"'";
如果,我们把userid="' or 1='1";
这样拼接的sql="select * from user where userid='' or 1='1'";
这样的sql就可列出表里的所有记录
对于一个好的程序员来说,编写高质量的代码,可以防止sql注入
比如使,用PreparedStatement来代替Statement来执行SQL语句,其后只是输入参数
SQL注入攻击手段将无效,这是因为PreparedStatement不允许在不同的插入时间改变查询的逻辑结构
大部分的SQL注入已经挡住了
有时候我们的sql语句是拼接,这样如果再重构我们的数据库操作的话,会很麻烦的
为此我们需要对表单中的非法字符进行过滤
当然,我们可以用Filter来实现,对提交到servlet的表单进行验证
但是,对于Struts2框架来说,似乎不起作用
这就需要用到struts2的拦截器来实现同样的功能
拦截器使用就不再介绍,网上很多
现在就我的实现代码贴出来供大家参考
IllegalCharacterInterceptor.java
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.util.ValueStack;
import com.sun.imageio.plugins.common.I18N;
public class IllegalCharacterInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
//通过核心调度器invocation来获得调度的Action上下文
ActionContext actionContext = invocation.getInvocationContext();
//获取Action上下文的值栈
ValueStack stack = actionContext.getValueStack();
//获取上下文的请求参数
Map valueTreeMap = actionContext.getParameters();
//获得请求参数集合的迭代器
Iterator iterator = valueTreeMap.entrySet().iterator();
//遍历组装请求参数
while(iterator.hasNext()){
//获得迭代的键值对
Entry entry = (Entry) iterator.next();
//获得键值对中的键值
String key = (String) entry.getKey();
//原请求参数,因为有可能一键对多值所以这里用的String[]
String[] oldValues = null;
//对参数值转换成String类型的
if(entry.getValue() instanceof String){
oldValues = new String[]{entry.getValue().toString()};
}else{
oldValues = (String[])entry.getValue();
}
//处理后的请求参数
String newValueStr = null;
//对请求参数过滤处理
if(oldValues.length>1){
newValueStr = "{" ;
for(int i=0 ;i<oldValues.length; i++){
//替换掉非法参数,这里只替换掉了',如有其他需求,可以专门写一个处理字符的类
newValueStr+=oldValues[i].toString().replaceAll("'","");
if(i!=oldValues.length-1){
newValueStr+=",";
}
}
newValueStr+="}";
}else if(oldValues.length==1){
//替换掉非法参数,这里只替换掉了',如有其他需求,可以专门写一个处理字符的类
newValueStr = oldValues[i].toString().replaceAll("'","");
}else{
newValueStr = null;
}
//处理后的请求参数加入值栈中
stack.setValue(key, newValueStr);
}
String result = null;
try {
// 调用下一个拦截器,如果拦截器不存在,则执行Action
result = invocation.invoke();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
拦截器写好后,就可以使用了
在struts.xml中配置自定义拦截器时,需把默认拦截器加上
不然默认拦截器会不起作用的
<interceptors>
<interceptor name="illegalCharacter" class="com.ainong.interceptor.IllegalCharacterInterceptor"/>
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="illegalCharacter"></interceptor-ref>
</interceptor-stack>
</interceptors>
这样就可使用myStack来拦截了
如果我们对于对每个Action都配置<interceptor-ref name="myStack"/>比较麻烦
我们也可把上面的拦截器栈,设置为默认拦截器栈,这样可以对package中的所有Action起作用
而不需要我们配置
<default-interceptor-ref name="myStack"></default-interceptor-ref>