使用預編譯語句是預防SQL注入的最佳方式

2021-09-19 15:58:25 字數 1657 閱讀 9162

sql 預編譯指的是資料庫驅動在傳送 sql 語句和引數給 dbms 之前對 sql 語句進行編譯,這樣 dbms 執行 sql 時,就不需要重新編譯。

jdbc 中使用物件 preparedstatement 來抽象預編譯語句,使用預編譯

預編譯階段可以優化 sql 的執行。

預編譯之後的 sql 多數情況下可以直接執行,dbms 不需要再次編譯,越複雜的sql,編譯的複雜度將越大,預編譯階段可以合併多次操作為乙個操作。

預編譯語句物件可以重複利用。

把乙個 sql 預編譯後產生的 preparedstatement 物件快取下來,下次對於同乙個sql,可以直接使用這個快取的 preparedstate 物件。

mybatis中預編譯:使用#{}語法,mybatis會產生preparedstatement語句中,並且安全的設定preparedstatement引數,這個過程中mybatis會進行必要的安全檢查和轉義。

示例1:

執行sql:select * from emp where name = #

引數:employeename=>smith

解析後執行的sql:select * from emp where name = ?

執行sql:select * from emp where name = $

引數:employeename傳入值為:smith

解析後執行的sql:select * from emp where name =smith

綜上所述、${}方式會引發sql注入的問題、同時也會影響sql語句的預編譯,所以從安全性和效能的角度出發,能使用#{}的情況下就不要使用${}。

1、能使用 # 的地方就用 #

首先這是為了效能考慮的,相同的預編譯 sql 可以重複利用。

其次, $ 在預編譯之前已經被變數替換了,這會存在 sql 注入問題 。例如,如下的 sql,

select * from $ where name = #
假如,我們的引數 tablename 為user; delete user; --,那麼 sql 動態解析階段之後,預編譯之前的 sql 將變為

select * from user; delete user; -- where name = ?;
--之後的語句將作為注釋,不起作用,因此本來的一條查詢語句偷偷的包含了乙個刪除表資料的 sql!

2、表名作為變數時,必須使用 $

這是因為,表名是字串,使用 sql 佔位符替換字串時會帶上單引號'',這會導致 sql 語法錯誤,例如:

select * from # where name = #;
預編譯之後的sql 變為:

select * from ? where name = ?;
假設我們傳入的引數為 tablename = "user" , name = "ruhua",那麼在佔位符進行變數替換後,sql 語句變為

select * from 'user' where name='ruhua';
上述 sql 語句是存在語法錯誤的,表名不能加單引號''(注意,反引號 ``是可以的)。

Python預編譯語句防止SQL注入

這個月太忙,最近不太太平,我的願望是世界和平!ps 直接引用別人的話了,因為他們說的已經很好了。錯誤用法 1 sql select id,type,name from xl bugs where id s and type s id,type 2 cur.execute sql 這種用法就是常見的拼...

SQL語句預編譯(查詢)

sql語句預編譯 sql語句預編譯能預防sql注入提高安全性,是因為sql語句在程式執行前已經進行了預編譯,在程式執行時第一次運算元據庫之前,sql語句已經被資料庫分析,編譯和優化,對應的執行計畫也會快取下來並允許資料庫以引數化的形式進行查詢,當執行時動態地把引數傳給preprarestatemen...

預編譯sql處理 防止sql注入

建立資料庫 create database jdbc demo default character set utf8 i 建立表 use jdbc demo create table admin id int primary key auto increment,username varchar 2...