激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - mybatis防止SQL注入的方法實例詳解

mybatis防止SQL注入的方法實例詳解

2021-04-24 11:15bwh0520 Java教程

SQL注入是一種很簡單的攻擊手段,但直到今天仍然十分常見。那么mybatis是如何防止SQL注入的呢?下面腳本之家小編給大家帶來了實例代碼,需要的朋友參考下吧

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

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

?
1
2
3
4
table user(
id varchar(20) primary key ,
name varchar(20) ,
age varchar(20) );

然后使用jdbc操作表:

?
1
2
3
4
5
6
7
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語句如下:

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

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

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

?
1
2
3
4
5
6
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注入攻擊

?
1
2
3
4
5
6
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);

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

?
1
2
3
4
5
6
7
8
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文件為:

?
1
2
3
<select id="getnamebyuserid" resulttype="string">
 select name from user where id = #{userid}
</select>

對應的java文件為:

?
1
2
3
public interface usermapper{
 string getnamebyuserid(@param("userid") string userid);
}

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

?
1
select name from user where id = ?

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

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

如果將上面的語句改成:

?
1
2
3
<select id="getnamebyuserid" resulttype="string">
 select name from user where id = ${userid}
</select>

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

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

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

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

總結

以上所述是小編給大家介紹的mybatis防止sql注入的方法實例詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!

原文鏈接:https://blog.csdn.net/bwh0520/article/details/80102040

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 美国黄色毛片女人性生活片 | 亚洲日韩精品欧美一区二区 | 美女黄色毛片免费看 | 一本在线高清码电影 | 国产欧美在线一区二区三区 | 国产成人午夜高潮毛片 | 91经典视频 | 欧美日韩精品中文字幕 | 毛片在线看免费 | 日本一级黄色毛片 | 九色91视频| 在线91视频 | 天天看夜夜爽 | 色人阁在线视频 | 九九热视频这里只有精品 | 亚洲一区在线免费视频 | 久久久国产一级片 | 毛片免费在线 | 欧美色性| 成人免费在线视频 | 免费高潮在线国 | 久久久久国产精品久久久久 | 欧美a在线看 | 99国产精品欲a | 欧美巨乳在线观看 | 久久精品日产高清版的功能介绍 | av免费在线观看国产 | 精品在线观看一区二区 | 精品久久久久久久 | 少妇一级淫片免费放播放 | 国产精品视频成人 | 欧美日韩精品一区二区三区在线观看 | 国产精品美女久久久免费 | 在线观看免费精品 | 91看片王 | xxxx18韩国护士hd老师 | 国产污污视频 | 欧美成人一区二区视频 | 好吊色37pao在线观看 | 日日草夜夜 | 国产一国产精品一级毛片 |