首先,SQL語句應該考慮哪些安全性? 第一,防止SQL註入,對特殊字元進行過濾、轉義或者使用預編譯的SQL語句綁定變數。 第二,當SQL語句運行出錯時,不要把資料庫返回的錯誤信息全部顯示給用戶,以防止泄露伺服器和資料庫相關信息。 其次,什麼叫做SQL註入呢,如何防止呢? 舉個例子: 你後臺寫的Jav ...
首先,SQL語句應該考慮哪些安全性?
第一,防止SQL註入,對特殊字元進行過濾、轉義或者使用預編譯的SQL語句綁定變數。
第二,當SQL語句運行出錯時,不要把資料庫返回的錯誤信息全部顯示給用戶,以防止泄露伺服器和資料庫相關信息。
其次,什麼叫做SQL註入呢,如何防止呢?
舉個例子:
你後臺寫的Java代碼拼的SQL如下:
1 //該ename為前臺傳過來的一個查詢條件
2 public List getInfo(String ename){
3 StringBuffer buf = new StringBuffer();
4 buf.append("select empno,ename,deptno from emp where ename = "").append(ename).append("");
5 ...
6 ...
7 }
而前臺頁面有輸入框如下:
職員姓名:
該文本域對應上面方法的ename參數。
如果用戶在查詢時向職員姓名文本域中輸入的是如下信息:
'or'1'='1
那麼這時就會涉及到SQL註入這個概念了。
上面的字元串傳到後臺後,與其他select等字元串拼成瞭如下的語句:
select empno,ename,deptno from emp where ename=" or '1'='1'
上面的where條件是永遠成立的,如果你的表中有許可權限制,比如只能查詢本地市的信息,過濾條件中有地市過濾,不過因為輸入'or'1'='1字元串後,條件永遠成立,導致你能看到所有城市的職員信息,那就會產生許可權問題了,用戶能看到不該看到的信息。同理,如果是insert或者update等語句的話,通過SQL諸如會產生不可估量的問題。
這種不安全的情況是在SQL語句在拼接的情況下發生。
解決方法:
1、參數綁定。為了防範這樣“SQL註入安全”可以用預編譯(不要用拼接SQL字元串,可以用prepareStatement,參數用set方法進行填裝)。
1 String sql="insert into userlogin values(?,?)";
2 try{
3 PrepareStatement ps = conn.prepareStatement(sql);
4 for(int i=1;i<100;i++){
5 ps.setInt(1,i);
6 ps.setInt(2,8888);
7 ps.executeUpdate();
8 }
9 ps.close();
10 conn.close();
11 }catch(SQLException e){
12 e.printStackTrace();
13 }
2、檢查變數的數據類型和格式
如果你的SQL語句市類似where id={$id}這種形式,資料庫里所有的id都是數字,那麼就應該在SQL被執行前,檢查確保變數id是int類型;如果是接受郵箱,那就應該檢查並嚴格確保變數一定是郵箱的格式,其他的類型比如日期、時間等也是一個道理。總結起來:只要是有固定格式的變數,在SQL語句執行前,應該嚴格固定格式去檢查,確保變數是我們預想的格式,這樣很大程度上可以避免SQL註入攻擊。
比如,我們前面接受username參數例子中,我們的產品設計應該是在用戶註冊的一開始,就有一個用戶名的命名規則,比如5-20個字元,只能由大小寫字母、數據以及一些安全的符號組成,不包含特殊字元。此時我們應該有一個check_username的函數來進行統一的檢查。不過,仍然有很多例外情況並不能應用到這一准則,比如文章發佈系統,評論系統等必須要允許客戶提交任意字元串的場景,這就需要採用過濾等其他方案了。(使用正則表達式進行格式驗證!)
3、所有的SQL語句都封裝在存儲過程中
所有的SQL語句都封裝在存儲過程中,這樣不但可以避免SQL註入,還能提高一些性能。