MyBatis中#{}和${}的深度解析:SQL注入與動態拼接的終極抉擇

MyBatis中#{}${}的深度解析:SQL注入與動態拼接的終極抉擇

摘要:在MyBatis的Mapper.xml文件中,#{}${}這兩個看似簡單的符號,卻隱藏著SQL安全與性能的核心秘密。本文將深入剖析它們的底層差異,并通過真實場景演示如何正確選擇,避免致命的安全漏洞!


一、符號初探:表面相似,本質不同

在MyBatis的SQL編寫中,我們經常看到這樣的寫法:

<!-- 使用# -->
<select id="getUser" resultType="User">SELECT * FROM user WHERE id = #{id}
</select><!-- 使用$ -->
<select id="getUser" resultType="User">SELECT * FROM user WHERE name = ${name}
</select>

表面看:兩者都用于參數替換
本質區別:它們的處理機制天差地別!

特性#{}${}
處理方式預編譯參數(PreparedStatement)字符串直接替換
防SQL注入? 安全? 高風險
數據類型轉換自動類型轉換需手動加引號
適用場景值傳遞(WHERE條件等)動態SQL片段(表名等)

二、底層原理:安全與危險的根源

1. #{} 的預編譯機制(安全衛士)
// MyBatis實際執行代碼(簡化版)
PreparedStatement ps = conn.prepareStatement("SELECT * FROM user WHERE id=?");
ps.setInt(1, 5);  // 安全!參數被嚴格處理

執行流程

  1. 將SQL語句編譯為模板
  2. 參數作為獨立數據傳入
  3. 數據庫引擎嚴格區分指令和數據
2. ${} 的字符串替換(危險陷阱)
// 假設傳入 name = "admin' OR '1'='1"
String sql = "SELECT * FROM user WHERE name=" + name; 
// 最終SQL:SELECT * FROM user WHERE name='admin' OR '1'='1'

注入風險:攻擊者可通過精心構造參數執行任意SQL!


三、實戰對比:當$遭遇SQL注入攻擊

場景:用戶登錄驗證
<!-- 危險寫法 -->
<select id="login" resultType="User">SELECT * FROM users WHERE username = ${username} AND password = ${password}
</select>

攻擊者輸入

username = "admin' -- "
password = "anything"

生成的致命SQL

SELECT * FROM users 
WHERE username = 'admin' -- ' AND password = 'anything'

結果:攻擊者無需密碼直接登錄管理員賬戶!

修復方案(改用#):
<select id="login" resultType="User">SELECT * FROM users WHERE username = #{username} AND password = #{password}
</select>

此時攻擊輸入將被轉義為:

WHERE username = 'admin'' -- ' AND ...

數據庫會嚴格查找用戶名為 admin' -- 的記錄,攻擊失效!


四、${}的正確打開方式:動態元數據操作

雖然${}有風險,但在特定場景下不可替代:

場景1:動態表名
<select id="getLogsByTable" resultType="Log">SELECT * FROM ${tableName} WHERE year = #{year}
</select>

:表名是SQL指令的一部分,無法使用預編譯占位符

場景2:動態排序
<select id="getUsers" resultType="User">SELECT * FROM usersORDER BY ${sortColumn} ${sortOrder}
</select>
安全規范:
  1. 白名單校驗:在Java代碼中校驗傳入的元數據
    // 表名白名單校驗
    Set<String> validTables = Set.of("log_2023","log_2024");
    if(!validTables.contains(tableName)) {throw new IllegalArgumentException("Invalid table name");
    }
    
  2. 避免用戶輸入:動態參數應來自系統內部,而非前端直接傳入

五、性能對比:# vs $的隱藏差異

操作#{}${}
SQL編譯首次編譯模板,后續復用每次生成全新SQL
數據庫緩存相同SQL模板可復用執行計劃每次被視為不同SQL,無法復用
執行10萬次編譯1次 + 執行10萬次編譯10萬次 + 執行10萬次
典型耗時≈1.5秒≈15秒(10倍差距!)

實測結論:高并發場景下,#{}的性能優勢極為明顯!


六、黃金法則:如何選擇符號

  1. 優先使用#{}

    • WHERE條件中的值
    • INSERT/UPDATE的字段值
    • 所有用戶輸入參數
  2. 謹慎使用${}

    • 動態表名/列名
    • ORDER BY排序子句
    • SQL關鍵字(如LIMIT)
    • 必須確保參數值內部可控!
  3. 絕對禁止

    <!-- 禁止將用戶輸入直接用于$ -->
    WHERE username = ${userInput}  ?
    

七、擴展技巧:#的高級用法

1. 類型處理器指定
<!-- 強制使用String類型處理器 -->
#{age, javaType=int, jdbcType=NUMERIC}
2. 日期格式轉換
#{createTime, jdbcType=TIMESTAMP, pattern="yyyy-MM-dd"}
3. 非空校驗
<!-- 當email為空時設置默認值 -->
#{email, jdbcType=VARCHAR, default='no-email@domain.com'}

結語

#{}${}的選擇本質是安全與靈活性的權衡:

  • #{} 是默認首選,保障安全與性能
  • ${} 是特定場景下的"手術刀",需嚴格管控

牢記:一次錯誤的${}使用可能導致整個系統淪陷!建議在團隊中制定《SQL編寫規范》,并配合SQL掃描工具(如SQLMap)定期檢測漏洞。

技術討論:你在項目中遇到過哪些${}引發的安全問題?歡迎評論區分享避坑經驗!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/86137.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/86137.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/86137.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

AWS多項目架構完全指南:基于App Runner的安全中轉服務設計

引言:云原生架構的演進之路 在數字化轉型浪潮中,企業常常面臨這樣的挑戰:如何在保證安全隔離的前提下,快速為多個項目部署服務,并實現與現有系統的無縫集成?本文將以真實案例為基礎,詳細介紹如何利用AWS App Runner、Transit Gateway和VPC連接器等現代化服務,構建高可…

Selenium操作指南

&#x1f345; 點擊文末小卡片&#xff0c;免費獲取軟件測試全套資料&#xff0c;資料在手&#xff0c;漲薪更快 大家好&#xff0c;今天帶大家一起系統的學習下模擬瀏覽器運行庫Selenium&#xff0c;它是一個用于Web自動化測試及爬蟲應用的重要工具。 Selenium測試直接運行在…

基于Qt開發的ModbusTcp主站軟件開發教程?——從協議原理到工業級實現

目錄 第一章 環境配置與庫集成1. 安裝Qt與Modbus模塊2. 第三方庫兼容性(備選方案)第二章 Modbus TCP協議與Qt類解析1. 協議核心要點2. Qt關鍵類說明第三章 主站連接管理與通信初始化1. 連接建立與斷線重連2. 請求超時與響應機制第四章 數據讀寫操作實戰1. 讀取保持寄存器(功…

什么是缺口箱線圖?如何繪制?

大家好&#xff0c;我是帶我去滑雪&#xff01; 箱線圖是一種用于展示數據分布特征的統計圖表&#xff0c;又稱為盒狀圖或盒須圖。它主要通過一個“箱子”和延伸出的“須”來展示一組數據的中位數、上下四分位數、最大值、最小值以及異常值。箱子的中線表示中位數&#xff0c;上…

在visual studio中為C++程序安裝缺失開源庫

在visual studio中測試一個代碼時出現include了一個之前沒用過的開源庫的情況&#xff0c;因為之前C用的少&#xff0c;這個問題比較基礎&#xff0c;也沒有找到能用的教程&#xff0c;就在這里記錄一下解決過程&#xff0c;以備不時之需。 顯然C和Visual Studio的組合不如pych…

CentOS加密技術全指南

文件系統加密 LUKS (Linux Unified Key Setup) 全盤加密配置方法 安裝前加密&#xff08;Anaconda安裝向導選項&#xff09; 在安裝CentOS時選擇"Encrypt my data"選項設置強密碼&#xff08;建議20字符&#xff0c;混合大小寫、數字和特殊符號&#xff09;密鑰槽管…

純血HarmonyOS5 打造小游戲實踐:繪畫板(附源文件)

OS 應用整體架構與技術棧 該繪圖應用采用了鴻蒙系統推薦的ArkUI框架進行開發&#xff0c;基于TypeScript語言編寫&#xff0c;充分利用了鴻蒙系統的圖形渲染和文件操作能力。應用整體架構遵循MVVM&#xff08;Model-View-ViewModel&#xff09;模式&#xff0c;通過State裝飾…

數據分析和可視化:Py爬蟲-XPath解析章節要點總結

重要知識點 XPath 概述&#xff1a;XPath 是一門可以在 XML 文件中查找信息的語言&#xff0c;也可用于 HTML 文件。它功能強大&#xff0c;提供簡潔明了的路徑表達式和多個函數&#xff0c;用于字符串、數值、時間比較等。1999 年成為 W3C 標準&#xff0c;常用于爬蟲中抓取網…

深入理解PHP中的生成器(Generators)

創建一個生成器非常簡單。你只需要像定義普通函數一樣定義它&#xff0c;但是使用yield關鍵字來產出值。例如&#xff0c;以下是一個簡單的斐波那契數列生成器&#xff1a; function fibonacci() {$num1 0;$num2 1;while (true) {yield $num1;$temp $num1 $num2;$num1 $n…

ubuntu 系統 pgm圖片和png相互轉化

ubuntu 系統 pgm圖片和png相互轉化。 安裝轉化工具&#xff1a; sudo apt-get install imagemagick pgm轉為png指令如下: convert input.pgm output.png png轉為pgm指令如下: convert input.png output.pgm

leetcode:98. 驗證二叉搜索樹

學習要點 加深純遞歸算法的理解 題目鏈接 98. 驗證二叉搜索樹 - 力扣&#xff08;LeetCode&#xff09; 題目描述 解法&#xff1a;純遞歸 vector<int> v;void dfs(TreeNode* root){if(root nullptr){return;}dfs(root->left);v.push_back(root->val);dfs(root…

如何確定IP的缺省子網掩碼是多少?

IP地址 201.100.200.1 的缺省子網掩碼由其 IP地址類別 決定。以下是判斷步驟&#xff1a; 1. 確定IP地址類別 IPv4地址分為 A、B、C、D、E 五類&#xff0c;根據第一個字節&#xff08;前8位&#xff09;的范圍劃分&#xff1a; A類&#xff1a;1.0.0.0 ~ 126.255.255.255&am…

Vue.js 粒子連線動畫組件 - FlyingLines

Vue.js 粒子連線動畫組件 - FlyingLines 使用指南 &#x1f31f; 簡介 FlyingLines 是一個基于 Vue.js 的炫酷粒子連線動畫組件&#xff0c;可以為您的網站添加動態的背景效果。該組件具有以下特點&#xff1a; ? 流暢動畫&#xff1a;基于 Canvas 的高性能渲染&#x1f5b…

無人機交互控制技術要點

一、技術要點 1. 物理交互設計 仿生柔性形態學&#xff1a;采用梯度剛度復合材料&#xff08;如硅膠-碳纖維&#xff09;設計柔性抓取器&#xff0c;模仿鳥類爪部結構&#xff0c;實現被動碰撞抑制與動態力生成&#xff0c;支持高速交互&#xff08;>3 m/s&#xff09;和…

qt集成openssl

第一&#xff1a;下載項目中對應版本的openssl的庫 https://openssl-library.org/source/old/1.0.2/ 老版本的openssl的下載地址&#xff0c;這個下載的好像是源碼&#xff0c;還要編譯。 https://indy.fulgan.com/SSL/ 在這里下載不需要編譯&#xff0c;下載下來直接用dll文件…

【鴻蒙HarmonyOS Next App實戰開發】??ArkUI時鐘界面實現解析:動態雙模式時鐘與沉浸式體驗?

在鴻蒙next系統上&#xff0c;通過ArkTS寫了個時鐘顯示頁面&#xff0c;集成在【圖影工具箱】應用中&#xff0c;應用商店可以下載使用。 這個頁面實現起來比較簡單&#xff0c;就是左邊一個模擬時鐘&#xff0c;右邊一個數字時鐘&#xff08;包含時間和日期的文字&#xff09…

ios簽名錯誤的解決辦法

另一種最常見的解決方案。在終端中運行以下命令。您應該添加自己的鑰匙串名稱和密碼。security lock-keychain temp.keychainsecurity unlock-keychain -pp ssw0rd temp.keychain在這種情況下&#xff0c;使用鑰匙串名稱為“temp”&#xff0c;其密碼為“p ssw0rd”。此外&am…

C#讀取OPCUA節點數據

本人第一次接觸OPCUA&#xff0c;如有不對的地方望指正&#xff0c;獲取的是公司的OPCUA服務器的數據 方式一&#xff1a; 測試環境: window11 vs2022 OPCFoundation.NetStandard.Opc.Ua .net framework 4.8 (2025-06-23 經過測試&#xff0c;.net8也可以使用這套.net …

OpenCV計算機視覺實戰(11)——邊緣檢測詳解

OpenCV計算機視覺實戰&#xff08;11&#xff09;——邊緣檢測詳解 0. 前言1. Sobel 算子與方向梯度1.1 Sobel 算子簡介1.2 實現過程 2. Laplacian 邊緣檢測2.1 Laplacian 算子簡介2.2 實現過程 3. Canny 算法3.1 Canny 算法簡介3.2 實現過程 小結系列鏈接 0. 前言 邊緣檢測能…

哈爾濱idc服務器租用-青蛙云

在數字化浪潮洶涌的當下&#xff0c;企業對于服務器的需求愈發強烈。哈爾濱作為東北地區重要的經濟文化中心&#xff0c;其 IDC 服務器租用市場也呈現出蓬勃發展的態勢。眾多企業在尋求 IDC 服務器租用時&#xff0c;青蛙云憑借自身顯著優勢脫穎而出&#xff0c;成為眾多用戶的…