首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

MyBatis 防止 SQL 注入的核心原理與最佳實踐

     編輯:Java 相關知識

為什麼要關注 SQL 注入?

SQL 注入是 Web 應用最常見的安全漏洞之一。攻擊者通過在表單或 URL 參數中植入惡意 SQL 片段(如 or '1'='1'),繞過業務邏輯竊取或破壞數據。銀行級系統常用存儲過程徹底隔離 SQL,但日常開發中,正確使用 MyBatis 的參數綁定機制即可有效防禦。

MyBatis 參數綁定的兩種語法

語法含義是否預編譯適用場景
#{param}佔位符參數✅ 是所有動態值(WHERE 條件、INSERT 值等)
${param}字符串直接拼接❌ 否表名、列名、排序字段等無法預編譯的標識符

#{ } 如何實現預編譯防注入?

<select id="getBlogById" resultType="Blog" parameterType="int">
  select id, title, author, content from blog where id = #{id}
</select>

執行時 MyBatis 將 SQL 發送給數據庫預編譯:

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

隨後僅傳遞參數值替換 ?。因為 SQL 結構在編譯階段已固化,攻擊者輸入的任何內容都會被視為普通字符串而非 SQL 片段,從而徹底杜絕注入。

底層原理:MyBatis 內部使用 JDBC PreparedStatement,其 setXxx() 方法會自動處理轉義與類型轉換。

${ } 的風險與應對策略

<select id="orderBlog" resultType="Blog" parameterType="map">
  select id, title, author, content from blog order by ${orderParam}
</select>

若 orderParam = "id; DROP TABLE blog;--",最終 SQL 變為:

select id, title, author, content from blog order by id; DROP TABLE blog;--

防禦措施:
1. 白名單校驗:在 Mapper 接口或 Service 層對 orderParam 嚴格匹配允許的列名集合。
2. 工具類轉義:引入 SQLUtils 或自寫正則過濾特殊字符。
3. 原則:能用 #{ } 絕不使用 ${ },只有標識符(表/列名)無法預編譯時才被迫使用 ${ } 並務必做嚴格校驗。

總結

  • MyBatis 預設通過 PreparedStatement 實現 SQL 預編譯,#{ } 是防注入的基石。
  • ${ } 會直接拼接 SQL,極易導致注入,僅限於動態表名/列名/排序字段等場景,並配合白名單校驗。
  • 代碼審查時重點檢查所有 ${ } 用法,確保經過安全過濾。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved