Mybatis防止sql注入原理

2021-08-30 17:27:54 字數 3529 閱讀 1060

sql注入是一種**注入技術,用於攻擊資料驅動的應用,惡意的sql語句被插入到執行的實體欄位中(例如,為了轉儲資料庫內容給攻擊者)。[摘自] sql注入 - 維基百科sql注入,大家都不陌生,是一種常見的攻擊方式。攻擊者在介面的表單資訊或url上輸入一些奇怪的sql片段(例如「或'1'='1'」這樣的語句),有可能入侵引數檢驗不足的應用程式。所以,在我們的應用中需要做一些,來防備這樣的攻擊方式。在一些安全性要求很高的應用(比如銀行軟體),經常使用將sql語句全部替換為儲存過程這樣的方式,來防止sql注入。當然這的英文一種很安全的方式,但我們平時開發中,可能不需要這種死板的方式。

mybatis的框架作為一款半自動化的orm框架,其sql語句都要我們自己手動編寫,這個時候當然需要防止sql注入。其實,mybatis的sql的是乙個具有「輸入+輸出」的功能,類似於函式的結構,如下:

getblogbyid 」resulttype =「 blog 」parametertype =「 int 」>

select id,title,author,content

from blog

where id =#

這裡,引數型別表示了輸入的引數型別,與resulttype表示了輸出的引數型別,回應上文,如果我們想防止sql注入,理所當然地要在輸入引數上下功夫。上面**中黃色高亮即輸入引數在sql中拼接的部分,傳入引數後,列印出執行的sql語句,會看到sql是這樣的:

select id,title,author,content from blog where id =?

。不管輸入什麼引數,列印出的sql都是這樣的這是因為mybatis的啟用了預編譯功能,在sql執行前,會先將上面的sql傳送給資料庫進行編譯;執行時,直接使用編譯好的sql ,替換佔位符「?」就可以了。因為sql注入只能對編譯過程起作用,所以這樣的方式就很好地避免了sql注入的問題。

【底層實現原理】

其原因就是:採用了jdbc的preparedstatement,就會將sql語句:「select id,no from user where id =?」 預先編譯好,也就是sql引擎會預先進行語法分析,產生語法樹,生成執行計畫,也就是說,後面你輸入的引數,無論你輸入的是什麼,都不會影響該sql語句的語法結構了,因為語法分析已經完成了,而語法分析主要是分析sql命令,比如select,from,where,and,or,order by等等。所以即使你後面輸入了這些sql命令,也不會被當成sql命令來執行了,因為這些sql命令的執行,必須先得通過語法分析,生成執行計畫,既然語法分析已經完成,已經預編譯過了,那麼後面輸入的引數,是絕對不可能作為sql命令來執行的,只會被當做字串字面值引數。所以的sql語句預編譯可以防禦sql注入。而且在多次執行同乙個sql時,能夠提高效率。原因是sql已編譯好,再次執行時無需再編譯。

話說回來,是否我們使用的mybatis就一定可以防止sql注入呢當然不是,請看下面的**?

getblogbyid 」resulttype =「 blog 」parametertype =「 int 」>

select id,title,author,content

from blog

where id = $

仔細觀察,內聯引數的格式由「」變為了「$」。如果我們給引數「id」賦值為「3」,將sql列印出來是這樣的:

select id,title,author,content from blog where id = 3

(上面的對比示例是我自己新增的,為了與前面的示例形成鮮明的對比。)

orderblog 」resulttype =「 blog 」parametertype =「 map 」>

select id,title,author,content

from blog

order by $

仔細觀察,內聯引數的格式由「」變為了「$」。如果我們給引數「orderparam」賦值為「id」,將sql列印出來是這樣的:

select id,title,author,content from blog order by id

顯然,這樣是無法阻止sql注入的。在mybatis中,「$」這樣格式的引數會直接參與sql編譯,從而不能避免注入攻擊。但涉及到動態表名和列名時,只能使用$「這樣的引數格式。所以,這樣的引數需要我們在**中手工進行處理來防止注入。

【結論】在編寫mybatis的對映語句時,盡量採用「」這樣的格式。若不得不使用「$」這樣的引數,要手工地做好過濾工作,來防止sql注入攻擊。

#{}:相當於jdbc中的preparedstatement的

$ {}:是輸出變數的值

簡單說,{}是經過預編譯的,是安全的;${}是未經過預編譯的,僅僅是取變數的值,是非安全的,存在sql注入。

如果我們通過語句後用了訂單$ {},那麼不做任何處理的時候是存在sql注入危險的。你說怎麼防止,那我只能悲慘的告訴你,你得手動處理過濾一下輸入的內容。如判斷一下輸入的引數的長度是否正常(注入語句一般很長),更精確的過濾則可以查詢一下輸入側的引數是否在預期的引數集合中。

mybatis防止sql注入

sql注入大家都不陌生,是一種常見的攻擊方式,攻擊者在介面的表單資訊或url上輸入一些奇怪的sql片段,例如 or 1 1 這樣的語句,有可能入侵引數校驗不足的應用程式 所以在我們的應用中需要做一些工作,來防備這樣的攻擊方式。在一些安全 性很高的應用中,比如銀行軟體,經常使用將sql語句全部替換為儲...

mybatis防止sql注入

sql注入大家都不陌生,是一種常見的攻擊方式,攻擊者在介面的表單資訊或url上輸入一些奇怪的sql片段,例如 or 1 1 這樣的語句,有可能入侵引數校驗不足的應用程式。所以在我們的應用中需要做一些工作,來防備這樣的攻擊方式。在一些安全性很高的應用中,比如銀行軟體,經常使用將sql語句全部替換為儲存...

mybatis 防止sql注入

1 和 符號的差異 相當於jdbc中的preparedstatement 相當於jdbc中的statement,使用字串拼接的形式 簡單說,是經過預編譯的,是安全的 是未經過預編譯的,僅僅是取變數的值,是非安全的,存在sql注入。使用時盡量使用 不得已使用 則相應對輸入值進行必要的校驗,防止sql注...