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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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;成为众多用户的…