在 Java 持久层框架中,MyBatis 因其灵活性和对 SQL 的精细控制而广受欢迎。然而,这种灵活性也带来了安全风险,尤其是 SQL 注入。许多开发者误以为只要使用了 MyBatis 就自动免疫 SQL 注入,事实并非如此。本文将梳理 MyBatis 中防止 SQL 注入的正确配置、常见误区,并延伸讨论 XSS 防御、MySQL 安全写法以及 Linux 服务器加固,帮助你在 Web 安全层面建立更完整的认知。
一、MyBatis 中 SQL 注入的根源:${} 与 #{}
MyBatis 提供了两种参数占位方式:
#{}:预编译参数,生成 JDBCPreparedStatement的?占位符,参数值通过setXxx()传入,数据库会将其视为纯数据,不会解析为 SQL 代码。${}:字符串拼接,直接将参数值拼接到 SQL 语句中,数据库会将其作为 SQL 语法的一部分解析。
正确做法:除非是动态表名、动态列名、ORDER BY 字段等无法使用预编译的场景,否则一律使用 #{}。
常见误区:
-
“用了 MyBatis 就不会有注入”
如果 SQL 中混用了${},注入依然存在。例如:<select id="getUser"> SELECT * FROM users WHERE name = '${name}' </select>当
name传入' OR '1'='1时,SQL 变为:SELECT * FROM users WHERE name = '' OR '1'='1'直接绕过条件。
-
“
${}只用在排序字段就安全”
排序字段同样可被注入。例如ORDER BY ${column},若column为id; DROP TABLE users--,在允许多语句执行时可能造成灾难。 -
“模糊查询必须用
${}”
正确写法是使用#{}配合CONCAT或数据库函数:<select id="search"> SELECT * FROM users WHERE name LIKE CONCAT('%', #{keyword}, '%') </select>而不是
LIKE '%${keyword}%'。 -
“动态表名无法防注入”
对于动态表名,应在 Java 层做白名单校验,只允许预定义的合法表名,再拼接到${}中。绝不能直接使用用户输入。
二、MyBatis 配置层面的加固建议
除了正确使用占位符,还可以从配置和代码层面增加防线:
- 开启
logPrefix与 SQL 日志审计:记录最终执行的 SQL,便于发现异常拼接。 - 使用 MyBatis-Plus 等增强工具时注意:其
QueryWrapper的apply方法若拼接字符串,同样可能引入注入。 - 限制数据库账号权限:MyBatis 使用的数据库账号不应具有
DROP、FILE、EXECUTE等高危权限。 - 统一封装动态排序:提供
OrderByUtils,将前端传入的排序字段映射为白名单枚举,再拼接到 SQL。
三、延伸:XSS 的常见方式与前端防御
SQL 注入针对数据库,XSS 则针对浏览器。常见 XSS 方式包括:
- 反射型:恶意脚本作为请求参数,服务器直接返回在页面中。
- 存储型:恶意脚本被存入数据库,其他用户访问时触发。
- DOM 型:前端 JavaScript 直接使用
innerHTML、document.write等插入不可信数据。
前端防御手段:
- 输出编码:根据上下文对数据进行 HTML、URL、JavaScript 编码。
- 使用安全 API:用
textContent代替innerHTML,用setAttribute代替直接拼接。 - CSP(内容安全策略):限制脚本来源,禁止内联脚本。
- 输入验证:不依赖前端验证作为唯一防线,但可减少误操作。
四、MySQL 防止 SQL 注入的几种写法
在数据库层面,除了依赖预编译,还可以:
- 使用
PREPARE语句:MySQL 支持服务端预编译,但通常由驱动完成。 - 严格模式与
NO_BACKSLASH_ESCAPES:避免转义绕过。 - 最小权限原则:应用账号只授予
SELECT、INSERT、UPDATE、DELETE等必要权限。 - 避免动态 SQL 拼接:存储过程内部也应使用参数化查询。
- 使用
mysql_real_escape_string(PHP 场景):但这不是最佳实践,预编译才是。
五、Linux 服务器安全加固清单
Web 安全不止于应用层,服务器加固是最后一道屏障:
- 更新与补丁:定期更新内核、OpenSSL、MySQL、Tomcat 等。
- 最小化服务:关闭不必要的端口和服务,使用
netstat或ss审查。 - SSH 加固:禁用 root 登录,使用密钥认证,修改默认端口,限制来源 IP。
- 防火墙:使用
iptables或firewalld只开放必要端口。 - 文件权限:Web 目录不可写,配置文件权限设为 600。
- 日志与监控:启用
auditd,集中收集日志,设置异常告警。 - 备份与恢复:定期备份数据库和关键配置,并演练恢复流程。
- WAF:部署 ModSecurity 等 Web 应用防火墙,拦截常见注入与 XSS 攻击。
六、总结
MyBatis 防 SQL 注入的核心只有一条:永远使用 #{},谨慎使用 ${},并对 ${} 的内容做白名单校验。误区往往源于对框架的过度信任和对动态 SQL 的随意拼接。将应用层、数据库层和服务器层的防护结合起来,才能有效抵御 SQL 注入、XSS 等常见 Web 威胁。安全不是某一个配置项,而是一套贯穿开发、部署、运维的实践习惯。
未经允许不得转载:任鹏个人博客 » MyBatis 中防止 SQL 注入的常见配置与误区


朋友圈点赞图在线生成源码