## 所謂SQL注入,就是通過把SQL命令插入到表單中或頁面請求的查詢字符串中,最終達到欺騙服務器執行惡意的SQL命令。 具體來說,它是利用現有應用程序,將(惡意的)SQL命令注入到后台數據庫引擎執行的能力, 它可以通過在Web表單中輸入(惡意)SQL語句得到一個存在安全漏洞的網站上的數據庫,而不是按照設計者意圖去執行SQL語句。 比如先前的很多影視網站泄露VIP會員密碼大多就是通過WEB表單遞交查詢字符暴出的。 ## 場景: 比如現在數據庫中有一個front_user表,表結構如下: class User(models.Model): telephone = models.CharField(max_length=11) username = models.CharField(max_length=100) password = models.CharField(max_length=100) 然后我們使用原生sql語句實現以下需求: 1.實現一個根據用戶id獲取用戶詳情的視圖。示例代碼如下: def index(request): user_id = request.GET.get('user_id') cursor = connection.cursor() cursor.execute("select id,username from front_user where id=%s" % user_id) rows = cursor.fetchall() for row in rows: print(row) return HttpResponse('success') 這樣表面上看起來沒有問題。但是如果用戶傳的user_id是等於1 or 1=1,那么以上拼接后的sql語句為: select id,username from front_user where id=1 or 1=1 以上sql語句的條件是id=1 or 1=1,只要id=1或者是1=1兩個有一個成立,那么整個條件就成立。毫無疑問1=1是肯定成立的。 因此執行完以上sql語句后,會將front_user表中所有的數據都提取出來。 2.實現一個根據用戶的username提取用戶的視圖。示例代碼如下: def index(request): username = request.GET.get('username') cursor = connection.cursor() cursor.execute("select id,username from front_user where username='%s'" % username) rows = cursor.fetchall() for row in rows: print(row) return HttpResponse('success') 這樣表面上看起來也沒有問題。但是如果用戶傳的username是zhiliao' or '1=1,那么以上拼接后的sql語句為: select id,username from front_user where username='zhiliao' or '1=1' 以上sql語句的條件是username='zhiliao'或者是一個字符串,毫無疑問,字符串的判斷是肯定成立的。因此會將front_user表中所有的數據都提取出來。 ################# sql注入防御: 以上便是sql注入的原理。他通過傳遞一些惡意的參數來破壞原有的sql語句以便達到自己的目的。 當然sql注入遠遠沒有這么簡單,我們現在講到的只是冰山一角。那么如何防御sql注入呢?歸類起來主要有以下幾點: 1.永遠不要信任用戶的輸入。對用戶的輸入進行校驗,可以通過正則表達式,或限制長度;對單引號和 雙"-"進行轉換等。 2.永遠不要使用動態拼裝sql,可以使用參數化的sql或者直接使用存儲過程進行數據查詢存取。比如: def index(request): user_id = "1 or 1=1" cursor = connection.cursor() cursor.execute("select id,username from front_user where id=%s",(user_id,)) rows = cursor.fetchall() for row in rows: print(row) return HttpResponse('success') 3.永遠不要使用管理員權限的數據庫連接,為每個應用使用單獨的權限有限的數據庫連接。 4.不要把機密信息直接存放,加密或者hash掉密碼和敏感的信息。 5.應用的異常信息應該給出盡可能少的提示,最好使用自定義的錯誤信息對原始錯誤信息進行包裝。 ## 在Django中如何防御sql注入: 1.使用ORM來做數據的增刪改查。因為ORM使用的是參數化的形式執行sql語句的。 2.如果萬一要執行原生sql語句,那么建議不要拼接sql,而是使用參數化的形式。