SQL注入、占位符拼接符


一、什么是SQL注入

 

官方:

所謂SQL注入,就是通過把SQL命令插入到Web表單提交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的SQL命令。具體來說,它是利用現有應用程序,將(惡意的)SQL命令注入到后台數據庫引擎執行的能力,它可以通過在Web表單中輸入(惡意)SQL語句得到一個存在安全漏洞的網站上的數據庫,而不是按照設計者意圖去執行SQL語句。

 

個人:

用戶在網頁輸入框中輸入SQL命令后,后台接收沒后沒有進行識別或類型轉換,而把它直接運行了。直接運行的話它可是可以直接操作數據庫的SQL命令,而不是后台期望的給SQL命令的普通參數。

 

記一次SQL注入實戰 http://blog.jobbole.com/105586/

 

二、Mybatis中的占位符和拼接符

1、占位符

(1)#{}表示一個占位符號,通過#{}把parameterType 傳入的內容通過preparedStatement向占位符中設置值,自動進行java類型和jdbc類型轉換,#{}可以有效防止sql注入。

(2)#{}可以接收簡單類型值或pojo屬性值。如果parameterType傳輸單個簡單類型值,#{}括號中可以是value或其它名稱。

例如(這是用JDBC編寫,在Mybatis中我們看不到PreparedStatement,只要是用占位符#{},它自動實現這過程):

 String sql = “insert into user (name,pwd) values(?,?)”;  
 PreparedStatement ps = conn.preparedStatement(sql);  
 ps.setString(1, “jack”);   //占位符順序從1開始
 ps.setString(2, “123456”); //也可以使用setObject
 ps.executeQuery();

 

2、拼接符

${}表示拼接sql串,通過${}可以將parameterType 傳入的內容直接拼接在sql中且不進行jdbc類型轉換,${}可以接收簡單類型值或pojo屬性值,如果parameterType傳輸單個簡單類型值,${}括號中只能是value。

 

三、為什么PreparedStatement 有效的防止sql注入?

 

1、PreparedStatement簡介

PreparedStatement是用來執行SQL查詢語句的API之一,Java提供了 Statement、PreparedStatement 和 CallableStatement三種方式來執行查詢語句,其中 Statement 用於通用查詢, PreparedStatement 用於執行參數化查詢,而 CallableStatement則是用於存儲過程。

 

2、普通SQL注入簡介

比如:某個網站的登錄驗證SQL查詢代碼為:

strSQL = "SELECT * FROM users WHERE name = '" + userName + "' and pw = '"+ passWord +"';"

 

惡意填入:

userName = "1' OR '1'='1";

passWord = "1' OR '1'='1";

 

那么最終SQL語句變成了:

strSQL = "SELECT * FROM users WHERE name = '1' OR '1'='1' and pw = '1' OR '1'='1';"

 

因為WHERE條件恆為真,這就相當於執行:

strSQL = "SELECT * FROM users;"

因此可以達到無賬號密碼亦可登錄網站。

 

3、使用PreparedStatement的參數化的查詢可以阻止大部分的SQL注入

 

在使用參數化查詢的情況下,數據庫系統(eg:MySQL)不會將參數的內容視為SQL指令的一部分來處理,而是在數據庫完成SQL指令的編譯后,才套用參數運行,因此就算參數中含有破壞性的指令,也不會被數據庫所運行。

即SQL語句在程序運行前已經進行了預編譯,當運行時動態地把參數傳給PreprareStatement時,即使參數里有敏感字符如 or '1=1'、數據庫也會作為一個參數一個字段的屬性值來處理而不會作為一個SQL指令。

 

補充1:在頁面輸入的時候可以加入校驗,不可輸入sql關鍵字,不可輸入空格,也可以防止SQL注入。

 

補充2:PreparedStatement比 Statement 更快

使用 PreparedStatement 最重要的一點好處是它擁有更佳的性能優勢,SQL語句會預編譯在數據庫系統中。執行計划同樣會被緩存起來,它允許數據庫做參數化查詢。使用預處理語句比普通的查詢更快,因為它做的工作更少(數據庫對SQL語句的分析,編譯,優化已經在第一次查詢前完成了)。為了減少數據庫的負載,生產環境中德JDBC代碼你應該總是使用PreparedStatement 。值得注意的一點是:為了獲得性能上的優勢,應該使用參數化sql查詢而不是字符串追加的方式。下面兩個SELECT 查詢,第一個SELECT查詢就沒有任何性能優勢。

SQL Query 1:字符串追加形式的PreparedStatement

String loanType = getLoanType();

PreparedStatement prestmt = conn.prepareStatement("select banks from loan where loan_type=" + loanType);

SQL Query 2:使用參數化查詢的PreparedStatement

PreparedStatement prestmt = conn.prepareStatement("select banks from loan where loan_type=?");

prestmt.setString(1,loanType);

很明顯Mybatis中是用的參數化查詢

 

 

參考:http://www.importnew.com/5006.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM