91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

mybatis如何防止SQL注入

發布時間:2021-07-15 11:26:31 來源:億速云 閱讀:156 作者:小新 欄目:編程語言

這篇文章主要介紹mybatis如何防止SQL注入,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

SQL注入是一種很簡單的攻擊手段,但直到今天仍然十分常見。究其原因不外乎:No patch for stupid。為什么這么說,下面就以JAVA為例進行說明:

假設數據庫中存在這樣的表:

table user( 
id varchar(20) PRIMARY KEY , 
name varchar(20) , 
age varchar(20) );

然后使用JDBC操作表:

private String getNameByUserId(String userId) { 
 Connection conn = getConn();//獲得連接 
String sql = "select name from user where id=" + userId; 
 PreparedStatement pstmt = conn.prepareStatement(sql); 
 ResultSet rs=pstmt.executeUpdate(); 
 ...... 
}

上面的代碼經常被一些開發人員使用。想象這樣的情況,當傳入的userId參數為"3;drop table user;"時,執行的sql語句如下:

select name from user where id=3; drop table user;

數據庫在編譯執行之后,刪除了user表。瞧,一個簡單的SQL注入攻擊生效了!之所以這樣,是因為上面的代碼沒有符合編程規范。

當我們按照規范編程時,SQL注入就不存在了。這也是避免SQL注入的第一種方式:預編譯語句,代碼如下:

 Connection conn = getConn();//獲得連接 
String sql = "select name from user where id= ?"; 
PreparedStatement pstmt = conn.prepareStatement(sql); 
pstmt.setString(1, userId); 
ResultSet rs=pstmt.executeUpdate(); 
....

為什么上面的代碼就不存在SQL注入了呢?因為使用了預編譯語句,預編譯語句在執行時會把"select name from user where id= ?"語句事先編譯好,這樣當執行時僅僅需要用傳入的參數替換掉?占位符即可。而對于第一種不符合規范的情況,程序會先生成sql語句,然后帶著用戶傳入的內容去編譯,這恰恰是問題所在。

除了使用預編譯語句之外,還有第二種避免SQL注入攻擊的方式:存儲過程。存儲過程(Stored Procedure)是一組完成特定功能的SQL語句集,經編譯后存儲在數據庫中,用戶通過調用存儲過程并給定參數(如果該存儲過程帶有參數)就可以執行它,也可以避免SQL注入攻擊

 Connection conn = getConn(); 
stmt = conn.prepareCall("{call name_from_user(?,?)}"); 
stmt.setInt(1,2); 
stmt.registerOutParameter(2, Types.VARCHAR); 
stmt.execute(); 
String name= stmt.getString(2);

上面的代碼中對應的存儲過程如下:

use user; 
delimiter // 
create procedure name_from_user(in user_id int,out user_name varchar(20)) 
begin 
 select name into user_name from user where id=user_id; 
end 
// 
delimiter ;

當然用戶也可以在前端做字符檢查,這也是一種避免SQL注入的方式:比如對于上面的userId參數,用戶檢查到包含分號就提示錯誤。

不過,從最根本的原因看,SQL注入攻擊之所以存在,是因為app在訪問數據庫時沒有使用最小權限。想來也是,大家好像一直都在使用root賬號訪問數據庫。

那么mybatis是如何避免sql注入攻擊的呢?還是以上面的表user為例:
假設mapper文件為:

<select id="getNameByUserId" resultType="String"> 
 SELECT name FROM user where id = #{userId} 
</select>

對應的java文件為:

public interface UserMapper{ 
 String getNameByUserId(@Param("userId") String userId); 
}

可以看到輸入的參數是String類型的userId,當我們傳入userId="34;drop table user;"后,打印的語句是這樣的:

select name from user where id = ?

不管輸入何種userID,他的sql語句都是這樣的。這就得益于mybatis在底層實現時使用預編譯語句。數據庫在執行該語句時,直接使用預編譯的語句,然后用傳入的userId替換占位符?就去運行了。不存在先替換占位符?再進行編譯的過程,因此SQL注入也就沒有了生存的余地了。

那么mybatis是如何做到sql預編譯的呢?其實框架底層使用的正是PreparedStatement類。PreparedStaement類不但能夠避免SQL注入,因為已經預編譯,當N次執行同一條sql語句時,節約了(N-1)次的編譯時間,從而能夠提高效率。

如果將上面的語句改成:

<select id="getNameByUserId" resultType="String"> 
 SELECT name FROM user where id = ${userId} 
</select>

當我們輸入userId="34;drop table user;"后,打印的語句是這樣的:

select name from user where id = 34;drop table user;

此時,mybatis沒有使用預編譯語句,它會先進行字符串拼接再執行編譯,這個過程正是SQL注入生效的過程。

因此在編寫mybatis的映射語句時,盡量采用“#{xxx}”這樣的格式。若不得不使用“${xxx}”這樣的參數,要手工地做好過濾工作,來防止sql注入攻擊。

以上是“mybatis如何防止SQL注入”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

比如县| 石棉县| 集安市| 海南省| 蒲城县| 黄龙县| 阳东县| 建德市| 澎湖县| 合江县| 绍兴县| 台南县| 漳浦县| 加查县| 尚义县| 汉寿县| 岐山县| 武宁县| 遂溪县| 洛扎县| 独山县| 千阳县| 大名县| 确山县| 丰城市| 友谊县| 丹阳市| 太谷县| 长海县| 台东市| 保康县| 嵊泗县| 兰坪| 堆龙德庆县| 舟曲县| 鞍山市| 拉萨市| 肥城市| 安吉县| 洛扎县| 汾阳市|