在日常開發中,SQL 注入是一種常見但危害巨大的安全漏洞。如果你正在使用 MyBatis 或 MyBatis-Plus 進行數據庫操作,這篇文章將帶你系統了解:這兩個框架是如何防止 SQL 注入的,我們又該如何寫出安全的代碼。
什么是 SQL 注入?
SQL 注入(SQL Injection)是指攻擊者通過輸入惡意 SQL 語句,干擾原本正常的數據庫查詢,從而達到繞過登錄、獲取數據、甚至刪除數據庫的目的。
舉個例子:
SELECT * FROM user WHERE name = 'admin' AND password = '123456' OR '1'='1'
如果我們將用戶輸入直接拼接到 SQL 中,攻擊者就可能利用 OR '1'='1'
這樣的語句,繞過身份驗證。
MyBatis 如何防止 SQL 注入?
使用 #{}
占位符(參數綁定)
MyBatis 的推薦做法是:使用 #{}
進行參數綁定。這是最有效的 SQL 注入防范方式。
<select id="selectUserByName" resultType="User">SELECT * FROM user WHERE name = #{name}
</select>
#{name}
會被轉換為 JDBC 的PreparedStatement
參數,占位符?
。- 由 MyBatis 自動將變量安全注入,避免注入風險。
避免 ${}
動態拼接
<select id="selectUserByName" resultType="User">SELECT * FROM user WHERE name = '${name}'
</select>
${}
會直接將用戶輸入拼接到 SQL 字符串中。- 攻擊者可以輸入
' OR 1=1 --
這樣的語句,造成嚴重后果。
總結:
- 使用
#{}
:安全 - 避免使用
${}
:易受攻擊
MyBatis-Plus 如何防止 SQL 注入?
MyBatis-Plus 是 MyBatis 的增強工具,大量簡化了開發。它默認使用參數綁定機制,在大多數情況下天然具備防注入能力。
條件構造器安全性
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name", userName);
userMapper.selectList(wrapper);
.eq("name", userName)
會使用PreparedStatement
自動綁定參數。- 比手寫 SQL 更簡潔也更安全。
apply 使用注意事項
有時候你可能需要執行一些復雜的 SQL 片段,比如使用 SQL 函數:
wrapper.apply("DATE_FORMAT(create_time,'%Y-%m-%d') = {0}", dateStr);
- 使用
{0}
綁定參數,是安全的。 - 直接拼接字符串不安全:
wrapper.apply("DATE_FORMAT(create_time,'%Y-%m-%d') = '" + dateStr + "'");
實戰建議
- 優先使用 MyBatis-Plus 提供的 API,如 Wrapper、LambdaQueryWrapper
- MyBatis XML 中,禁止使用
${}
,一律使用#{}
- 自定義 SQL 時,確保參數使用綁定方式
- 開啟 SQL 日志,排查拼接風險
- 可選:配合 SQL 審計工具做自動掃描
如果你覺得這篇文章對你有幫助,不妨點個贊