SQL注入、佔位符拼接符

目錄

一、什麼是SQL注入 

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

三、爲什麼PreparedStatement 有效的防止sql注入?

一、什麼是SQL注入 

官方:

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

個人:

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

二、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注入?

1PreparedStatement簡介

PreparedStatement是用來執行SQL查詢語句的API之一,Java提供了 StatementPreparedStatement  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注入。

補充2PreparedStatement 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中是用的參數化查詢

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章