防止SQL注入

最近,師弟們維護的教務系統出了點問題,存在sql注入漏洞,老闆讓我給他們看看,於是乎在網上查找了一番,又看了看項目的代碼,項目使用的是statement,決定換成preparedStatement.

Statement是PreparedStatement的父接口,不進行預編譯操作,減少了進行預編譯的開銷.單次運行

PreparedStatement可以實現Statement的所有功能,但是之所以叫它預編譯指令,是因爲在創建它的一個對象時可以給定具有一定格式的SQL字符串,然後用它的setXXX方法給指定的SQL語句以填空的方式賦值,具有這樣的特性後,它在多次執行一條固定格式的字符串時就很方便,也更效率.不像Statement那樣每次執行都要先編譯字符串在執行SQL了.

Oracle中會將所有的SQL語句先編譯,叫做"執行計劃",放在Oracle內部的一個特定的緩存中,每次遇到相同的SQL,就會先調用緩存中的,如果不預編譯,每次都用Statement,那麼每次都要編譯,在緩衝中會有很多重複的"執行計劃"影響數據庫的性能.還有一點就是在使用setObject()的時候,記得一定要使用帶targetSqlType參數的方法,來提高效率.

SQL注入***是利用設計上的漏洞,在目標服務器上運行SQL語句進行***,動態生成SQL語句時沒有對用戶輸入的數據進行驗證是SQL注入***得逞的主要原因.對於JDBC而言,SQL注入***只對Statement有效,對PreparedStatement是無效的,這是因爲PreparedStatement不允許在插入時改變查詢的邏輯結構.繞過驗證,但這種手段只對Statement有效,對PreparedStatement無效.

如果有一條SQL語句: "select * from 表 where 用戶名 = '用戶名'"
Statement的SQL語句是這樣寫的: "select * from 表 where 用戶名 = '"+ 變量值 +"'"
PreparedStatement的SQL語句是這樣寫的: "select * from 表 where 用戶名 = ?" 然後對應?賦值
這樣我們就發現輸入 "aa' or '1' = '1"
Statement是將這個和SQL語句做字符串連接到一起執行。PreparedStatement是將 "aa' or '1' = '1" 作爲一個字符串賦值給?,做爲"用戶名"字段的對應值,顯然這樣SQL注入無從談起了.

實現機制不同,注入只對SQL語句的準備(編譯)過程有破壞作用,而PreparedStatement已經準備好了,執行階段只是把輸入串作爲數據處理,不再需要對SQL語句進行解析,準備,因此也就避免了SQL注入問題.




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章