sql注入過濾器

上一篇文章中弄完了xss過濾器,今天來弄一下防sql注入的過濾器儒喊。為什么呢镣奋?我怎么知道為什么,去問問產(chǎn)品經(jīng)理/客戶吧怀愧∏染保總之,像這種安全性的過濾器芯义,就像一個藤上的葫蘆娃一樣哈垢,一個接著一個的出現(xiàn)。平時沒有啥作用毕贼,但關(guān)鍵時候來個合體温赔,能將邪惡的大魔王擋在門外蛤奢。

現(xiàn)在后端的框架也做了防止sql注入的手段鬼癣,比如使用PreparedStatement+占位符。但加一層過濾器總歸更加安全一點啤贩。這里的防sql注入的過濾器可以對普通get/post請求進(jìn)行參數(shù)過濾待秃,也可以對post+application/json等請求進(jìn)行參數(shù)過濾。該過濾器使用了請求的包裝類痹屹,具體參考我的上一篇文章章郁。

好,現(xiàn)在是代碼時刻志衍,把這個防sql注入過濾器放在xss過濾器之前暖庄。為什么呢?因為xss過濾器會把一些字符進(jìn)行轉(zhuǎn)義楼肪,這個時候如果再進(jìn)行防sql注入的過濾培廓,就會讓該過濾器以為是sql注入的請求,就會報錯春叫。

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 wjp
 * 
 */
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) {
    }
}

烏拉拉晨横,這樣就寫完了洋腮。好廉沮,打完收工。旁邊的前端妹子向我投來羨慕的眼神徐矩,我心里好亂滞时,難道我的代碼注釋寫的很好嘛,可我覺得一般吧滤灯。算了坪稽,不要在意這些細(xì)節(jié),我還是去搭地鐵吧鳞骤。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末窒百,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子豫尽,更是在濱河造成了極大的恐慌篙梢,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件美旧,死亡現(xiàn)場離奇詭異渤滞,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)榴嗅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門妄呕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人嗽测,你說我怎么就攤上這事绪励。” “怎么了唠粥?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵疏魏,是天一觀的道長。 經(jīng)常有香客問我晤愧,道長大莫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任养涮,我火速辦了婚禮葵硕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘贯吓。我一直安慰自己懈凹,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布悄谐。 她就那樣靜靜地躺著介评,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上们陆,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天寒瓦,我揣著相機(jī)與錄音,去河邊找鬼坪仇。 笑死杂腰,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的椅文。 我是一名探鬼主播喂很,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼皆刺!你這毒婦竟也來了少辣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤羡蛾,失蹤者是張志新(化名)和其女友劉穎漓帅,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痴怨,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡忙干,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了腿箩。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片豪直。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖珠移,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情末融,我是刑警寧澤钧惧,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站勾习,受9級特大地震影響浓瞪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜巧婶,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一乾颁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧艺栈,春花似錦英岭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春吭狡,著一層夾襖步出監(jiān)牢的瞬間尖殃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工划煮, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留送丰,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓弛秋,卻偏偏與公主長得像蚪战,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子铐懊,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容