現(xiàn)在后端的框架也做了防止sql注入的手段慨畸,比如使用PreparedStatement+占位符莱坎。但加一層過濾器總歸更加安全一點。這里的防sql注入的過濾器可以對普通get/post請求進行參數(shù)過濾寸士,也可以對post+application/json等請求進行參數(shù)過濾檐什。
該過濾器使用了請求的包裝類,具體參考我的上一篇文章http://www.reibang.com/p/579558b6dc63
弱卡,這里只給出過濾參數(shù)的部分:
package cn.wjp.mydaily.common.filter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import javax.servlet.FilterConfig;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
/**
* 防止SQL注入的攔截器 放在xssFilter之后 xssFilter轉(zhuǎn)義之后的字符會被該過濾器當(dāng)作sql注入
* @author
* @time 20190425
*/
public class SqlInjectFilter implements Filter {
/**
* 需要過濾的sql關(guān)鍵字乃正,可以手動添加
*/
public static final String BAD_PARAM_STR ="'|and|exec|execute|insert|select|delete|update|count|drop|*|%|chr|mid|master|truncate|" +
"char|declare|sitename|net user|xp_cmdshell|;|or|-|+|,|like'|and|exec|execute|insert|create|drop|" +
"table|from|grant|use|group_concat|column_name|" +
"information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|*|" +
"chr|mid|master|truncate|char|declare|or|;|-|--|+|,|like|//|/|%|#";
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request =(HttpServletRequest)req;
HttpServletResponse response =(HttpServletResponse)res;
String contentType = request.getContentType();//獲取contentType請求頭
String method = request.getMethod();//獲取請求方法 post/get
//1 處理get請求 get請求的Content-Type一般為application/x-www-form-urlencoded 或者 text/html
if(method.trim().equalsIgnoreCase(HttpConst.GET_METHOD)){
if(isValidParamForGet(request)){
chain.doFilter(request, response);
return;
}else {
response.sendError(403,"發(fā)送的參數(shù)可能會引起sql注入,系統(tǒng)拒絕服務(wù)婶博!");
return;
}
}
//2 處理post請求 只處理application/x-www-form-urlencoded application/json,對于multipart/form-data瓮具,直接放行
if(method.trim().equalsIgnoreCase(HttpConst.POST_METHOD)){
if(contentType.trim().toLowerCase().contains(HttpConst.MULTIPART_CONTENT_TYPE)){
chain.doFilter(request, response);
return;
}
//處理application/x-www-form-urlencoded
if(contentType.trim().toLowerCase().contains(HttpConst.FORM_URLENCODED_CONTENT_TYPE)){
if(isValidParamForPost(request)){
chain.doFilter(request, response);
return;
}else {
response.sendError(403,"發(fā)送的參數(shù)可能會引起sql注入,系統(tǒng)拒絕服務(wù)凡人!");
return;
}
}
//處理application/json
if(contentType.trim().toLowerCase().contains(HttpConst.JSON_CONTENT_TYPE)){
HttpServletRequestBodyReaderWrapper wrapperRequest = new HttpServletRequestBodyReaderWrapper(request);
String body = wrapperRequest.getBody();
if(isValidParamForJsonPost(body)){
chain.doFilter(wrapperRequest, response);
return;
}else {
response.sendError(403,"發(fā)送的參數(shù)可能會引起sql注入名党,系統(tǒng)拒絕服務(wù)!");
return;
}
}
}
chain.doFilter(request, response);
return;
}
//sql注入效驗
protected static boolean isSqlValidate(String str) {
if(str==null||str.trim().isEmpty()){
return true;
}
str = str.toLowerCase();//統(tǒng)一轉(zhuǎn)為小寫
String[] badStrs = BAD_PARAM_STR.split("\\|");
for (int i = 0; i < badStrs.length; i++) {
if (Pattern.matches("^"+badStrs[i]+"$",str)) {
return false;
}
}
return true;
}
/**
* get請求的參數(shù)是否無害 無害:true 有害:false
* @param request
* @return
*/
public boolean isValidParamForGet(HttpServletRequest request){
Enumeration params = request.getParameterNames();//獲得所有請求參數(shù)名
System.out.println("SqlInjectFilter:發(fā)送的請求參數(shù)值串:"+params);
while (params.hasMoreElements()) {
String name = params.nextElement().toString(); //得到參數(shù)名
String[] value = request.getParameterValues(name);//得到參數(shù)對應(yīng)值
if(!isSqlValidate(name)){
return false;
}
for (int i = 0; i < value.length; i++) {
if(!isSqlValidate(value[i])){
return false;
}
}
}
return true;
}
/**
* post請求的參數(shù)是否無害 無害:true 有害:false
* @param request
* @return
*/
public boolean isValidParamForPost(HttpServletRequest request){
return isValidParamForGet(request);
}
/**
* post請求的參數(shù)是否無害 無害:true 有害:false
* @param body 請求體
* @return
*/
public boolean isValidParamForJsonPost(String body){
System.out.println("SqlInjectFilter:發(fā)送的請求參數(shù)值串:"+body);
if(body==null||body.trim().isEmpty()||body.trim().equalsIgnoreCase("{}")||!body.trim().contains(":")){
return true;
}
Map<String,Object> map = JSON.parseObject(body,new TypeReference<Map<String,Object>>(){});
if(map==null||map.size()==0){
return true;
}
for (Map.Entry<String,Object> entry : map.entrySet()) {
String key = entry.getKey();
if(!isSqlValidate(key)){
return false;
}
Object value = entry.getValue();
String valueStr = String.valueOf(value);
if(valueStr==null||valueStr.trim().isEmpty()||valueStr.trim().equalsIgnoreCase("null")){
valueStr = null;
}
if(!isSqlValidate(valueStr)){
return false;
}
}
return true;
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig arg0) {
}
}