#{}與${}的區(qū)別

本文摘自:https://blog.csdn.net/qian_qian_123/article/details/92844194

※:PreparedStatement不允許在插入?yún)?shù)時(shí)改變SQL語(yǔ)句的邏輯結(jié)構(gòu)俱饿。

※:為什么它這樣處理就能預(yù)防SQL注入提高安全性呢暇咆?其實(shí)是因?yàn)镾QL語(yǔ)句在程序運(yùn)行前已經(jīng)進(jìn)行了預(yù)編譯,在程序運(yùn)行時(shí)第一次操作數(shù)據(jù)庫(kù)之前云矫,SQL語(yǔ)句已經(jīng)被數(shù)據(jù)庫(kù)分析抒和,編譯和優(yōu)化矫渔,對(duì)應(yīng)的執(zhí)行計(jì)劃也會(huì)緩存下來(lái)并允許數(shù)據(jù)庫(kù)已參數(shù)化的形式進(jìn)行查詢,當(dāng)運(yùn)行時(shí)動(dòng)態(tài)地把參數(shù)傳給PreprareStatement時(shí)构诚,即使參數(shù)里有敏感字符如 or '1=1'也數(shù)據(jù)庫(kù)會(huì)作為一個(gè)參數(shù)一個(gè)字段的屬性值來(lái)處理而不會(huì)作為一個(gè)SQL指令蚌斩,如此,就起到了防止SQL注入的作用了范嘱!

經(jīng)常碰到這樣的面試題目:#{}和${}的區(qū)別是什么送膳?

網(wǎng)上的答案是:#{}是預(yù)編譯處理,$ {}是字符串替換丑蛤。mybatis在處理#{}時(shí)叠聋,會(huì)將sql中的#{}替換為?號(hào),調(diào)用PreparedStatement的set方法來(lái)賦值受裹;mybatis在處理 $ { } 時(shí)碌补,就是把 ${ } 替換成變量的值。使用 #{} 可以有效的防止SQL注入棉饶,提高系統(tǒng)安全性厦章。

對(duì)于這個(gè)題目我感覺(jué)要抓住兩點(diǎn):

(1)$ 符號(hào)一般用來(lái)當(dāng)作占位符,常使用Linux腳本的人應(yīng)該對(duì)此有更深的體會(huì)吧照藻。既然是占位符袜啃,當(dāng)然就是被用來(lái)替換的。知道了這點(diǎn)就能很容易區(qū)分$和#幸缕,從而不容易記錯(cuò)了群发。

(2)預(yù)編譯的機(jī)制晰韵。預(yù)編譯是提前對(duì)SQL語(yǔ)句進(jìn)行預(yù)編譯,而其后注入的參數(shù)將不會(huì)再進(jìn)行SQL編譯熟妓。我們知道雪猪,SQL注入是發(fā)生在編譯的過(guò)程中,因?yàn)閻阂庾⑷肓四承┨厥庾址鹩詈蟊痪幾g成了惡意的執(zhí)行操作只恨。而預(yù)編譯機(jī)制則可以很好的防止SQL注入。

最后想說(shuō)的是抬虽,對(duì)于mybatis 以及 sql 而言坤次,每一個(gè)考點(diǎn)背后都是有一個(gè)深刻的思想存在的,應(yīng)該好好的體會(huì)斥赋。這樣才能真正的做到技術(shù)提升缰猴,成為技術(shù)大牛。

${param}傳遞的參數(shù)會(huì)被當(dāng)成sql語(yǔ)句中的一部分疤剑,比如傳遞表名滑绒,字段名

例子:(傳入值為id)

orderby${param}

則解析成的sql為:

orderbyid

#{parm}傳入的數(shù)據(jù)都當(dāng)成一個(gè)字符串,會(huì)對(duì)自動(dòng)傳入的數(shù)據(jù)加一個(gè)雙引號(hào)

例子:(傳入值為id)

select*fromtablewherename =#{param}

則解析成的sql為:

select*fromtablewherename ="id"

為了安全隘膘,能用#的地方就用#方式傳參疑故,這樣可以有效的防止sql注入攻擊

sql注入簡(jiǎn)介

直接上了百度的例子,感覺(jué)一看就清晰明了

某個(gè)網(wǎng)站的登錄驗(yàn)證的SQL查詢代碼為:

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

惡意填入

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

與passWord?="1'?OR?'1'='1";

時(shí)弯菊,將導(dǎo)致原本的SQL字符串被填為

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

也就是實(shí)際上運(yùn)行的SQL命令會(huì)變成下面這樣的

strSQL?="SELECT?*?FROM?users;"

這樣在后臺(tái)帳號(hào)驗(yàn)證的時(shí)候巧妙地繞過(guò)了檢驗(yàn)纵势,達(dá)到無(wú)賬號(hào)密碼,亦可登錄網(wǎng)站管钳。所以SQL注入攻擊被俗稱為黑客的填空游戲钦铁。

動(dòng)態(tài) sql 是 mybatis 的主要特性之一,在 mapper 中定義的參數(shù)傳到 xml 中之后才漆,在查詢之前 mybatis 會(huì)對(duì)其進(jìn)行動(dòng)態(tài)解析牛曹。mybatis 為我們提供了兩種支持動(dòng)態(tài) sql 的語(yǔ)法:#{} 以及 ${}。

  在下面的語(yǔ)句中醇滥,如果 username 的值為 zhangsan黎比,則兩種方式無(wú)任何區(qū)別:

select * from user where name = #{name};

select * from user where name = ${name};

其解析之后的結(jié)果均為

select * from user where name = 'zhangsan';

但是 #{} 和 ${} 在預(yù)編譯中的處理是不一樣的。#{} 在預(yù)處理時(shí)鸳玩,會(huì)把參數(shù)部分用一個(gè)占位符 ? 代替阅虫,變成如下的 sql 語(yǔ)句:

select * from user where name = ?;

而 ${} 則只是簡(jiǎn)單的字符串替換,在動(dòng)態(tài)解析階段不跟,該 sql 語(yǔ)句會(huì)被解析成

select * from user where name = 'zhangsan';

以上颓帝,#{} 的參數(shù)替換是發(fā)生在 DBMS 中,而 ${} 則發(fā)生在動(dòng)態(tài)解析過(guò)程中。

  那么躲履,在使用過(guò)程中我們應(yīng)該使用哪種方式呢?

  答案是聊闯,優(yōu)先使用 #{}工猜。因?yàn)?${} 會(huì)導(dǎo)致 sql 注入的問(wèn)題×馐撸看下面的例子:

select * from ${tableName} where name = #{name}

在這個(gè)例子中篷帅,如果表名為

  ?user; delete user; --?

  則動(dòng)態(tài)解析之后 sql 如下:

select * from user; delete user; -- where name = ?;

--之后的語(yǔ)句被注釋掉,而原本查詢用戶的語(yǔ)句變成了查詢所有用戶信息+刪除用戶表的語(yǔ)句拴泌,會(huì)對(duì)數(shù)據(jù)庫(kù)造成重大損傷魏身,極大可能導(dǎo)致服務(wù)器宕機(jī)。

  但是表名用參數(shù)傳遞進(jìn)來(lái)的時(shí)候蚪腐,只能使用 ${} 箭昵,具體原因可以自己做個(gè)猜測(cè),去驗(yàn)證回季。這也提醒我們?cè)谶@種用法中要小心sql注入的問(wèn)題家制。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市泡一,隨后出現(xiàn)的幾起案子颤殴,更是在濱河造成了極大的恐慌,老刑警劉巖鼻忠,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涵但,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡帖蔓,警方通過(guò)查閱死者的電腦和手機(jī)矮瘟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)塑娇,“玉大人芥永,你說(shuō)我怎么就攤上這事《鬯保” “怎么了埋涧?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)奇瘦。 經(jīng)常有香客問(wèn)我棘催,道長(zhǎng),這世上最難降的妖魔是什么耳标? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任醇坝,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘呼猪。我一直安慰自己画畅,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布宋距。 她就那樣靜靜地躺著轴踱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪谚赎。 梳的紋絲不亂的頭發(fā)上淫僻,一...
    開(kāi)封第一講書(shū)人閱讀 49,929評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音壶唤,去河邊找鬼雳灵。 笑死,一個(gè)胖子當(dāng)著我的面吹牛闸盔,可吹牛的內(nèi)容都是我干的悯辙。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼迎吵,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼笑撞!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起钓觉,我...
    開(kāi)封第一講書(shū)人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤茴肥,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后荡灾,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體瓤狐,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年批幌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了础锐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡荧缘,死狀恐怖皆警,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情截粗,我是刑警寧澤信姓,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站绸罗,受9級(jí)特大地震影響意推,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜珊蟀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一菊值、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦腻窒、人聲如沸昵宇。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)瓦哎。三九已至,卻和暖如春典徊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背恩够。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工卒落, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蜂桶。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓儡毕,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親扑媚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子腰湾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350