批量in查詢中可能會導致的sql注入問題
來源:程序員人生 發布時間:2014-10-04 08:00:00 閱讀次數:3532次
有時間我們在使用in或者or進行查詢時,為了加快速度,可能會經常這樣來使用sql之間的拼接,然后直接導入到一個in中,這種查詢實際上性能上還是可以的,
例如如下:
update keyword set stats=? where taskid in ('"+CollUtil.toString(list, "','")+"') "
當然這個in里面包含的是一些列的數據()但是如果這些數據中包含一些sql比較敏感的關鍵詞或者符號就會出現sql注入,例如如果in查詢中出現一個關鍵詞為(百度' )這個單引號在sql中就是比較敏感的字符,這就會導致你的這條語句執行失敗。如果我們在寫代碼時如果不注意這些問題,就會引起一些黑客們的攻擊,例如:如果某個黑客搞個語句,里面含有MySQL識別的注釋符號,然后黑客通過拼接好后 直接執行一個delete操作,那么你的數據庫系統就這樣完蛋了。
實際上面對這些問題,我們最好不要通過自己排除的方式來,因為很可能出現我們意想不到的情況出現,所以我們在進行無論查詢或者更改插入之類的操作時,最好使用問號表達式,這樣能夠防注入。
但是如果有些特殊情況下,我們的系統使我們內部使用,我們也可以是適當的使用in或者or查詢,但是我們在in()這個括號里面要注意數量問題,這個問題因不同的版本in中包含的量估計都是不一樣的。我們最好可以通過一些算法來控制這個量,最好是自己做一下壓力測試,看看到底你的in中能夠包含多大的數據量,當然我曾經做過壓力測試,in里面可以包含16W多,當時我是包含了64個字長的英語字母和漢字,在進行操作時,可能會因為字段的長度不同,速度肯定都會不同。
int size = ids.size();
int loopNum = (size%1000==0)?(size/1000):(size/1000 + 1);
if(size==0){
return;
}
for(int cp=1;cp<=loopNum;cp++){
int beginRecord = (cp - 1) * 1000;
int endRecord = cp*1000;
if(endRecord >= size){
endRecord = size;
}
// 分批進行任務獲取
List<String> list = ids.subList(beginRecord, endRecord);
當然我這只是一個分組算法的實例,我們平常在使用這種性能不是太好的查詢是也要注意分組進行,如果不這樣,MySQL可能會報一些packet過大的異常或者請檢查你的版本異常,如果你發現你的sql語句沒有問題,這時你就該應該注意到這個問題了。
還有一點,我們在一個函數中進行寫sql語句時,如果一條sql能夠搞定,我們也盡量不要使用第二條,因為數據庫的打開與關閉是非常耗時的操作,所以我們在使用編程語言進行寫程序時,要盡量使用我們工具類中給我們提供的一些類,例如:
StringBuffer buffer = new StringBuffer();
buffer.append("update keyword set stats=? ");
paramsList.add(stats);
if(stats==Stats.pend.getCode()){
buffer.append(",pend=? ");
paramsList.add(new Date());
}
buffer.append(" where taskid in ('"+CollectionUtil.toString(list, "','")+"') ");
這樣如果在滿足2條sql語句的情況下,實際上1條sql就直接搞定了。這樣還能夠增加代碼執行的速度。特別是數據量特別大的情況下,更要減少一個函數中的sql語句,盡量使用拼接,減少數據庫的打開與關閉。
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈