MyBatis 中防止 SQL 注入的常见配置与误区

在 Java 持久层框架中,MyBatis 因其灵活性和对 SQL 的精细控制而广受欢迎。然而,这种灵活性也带来了安全风险,尤其是 SQL 注入。许多开发者误以为只要使用了 MyBatis 就自动免疫 SQL 注入,事实并非如此。本文将梳理 MyBatis 中防止 SQL 注入的正确配置、常见误区,并延伸讨论 XSS 防御、MySQL 安全写法以及 Linux 服务器加固,帮助你在 Web 安全层面建立更完整的认知。

一、MyBatis 中 SQL 注入的根源:${}#{}

MyBatis 提供了两种参数占位方式:

  • #{}:预编译参数,生成 JDBC PreparedStatement? 占位符,参数值通过 setXxx() 传入,数据库会将其视为纯数据,不会解析为 SQL 代码。
  • ${}:字符串拼接,直接将参数值拼接到 SQL 语句中,数据库会将其作为 SQL 语法的一部分解析。

正确做法:除非是动态表名、动态列名、ORDER BY 字段等无法使用预编译的场景,否则一律使用 #{}

常见误区

  1. “用了 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'
    

    直接绕过条件。

  2. ${} 只用在排序字段就安全”
    排序字段同样可被注入。例如 ORDER BY ${column},若 columnid; DROP TABLE users--,在允许多语句执行时可能造成灾难。

  3. “模糊查询必须用 ${}
    正确写法是使用 #{} 配合 CONCAT 或数据库函数:

    <select id="search">
        SELECT * FROM users WHERE name LIKE CONCAT('%', #{keyword}, '%')
    </select>
    

    而不是 LIKE '%${keyword}%'

  4. “动态表名无法防注入”
    对于动态表名,应在 Java 层做白名单校验,只允许预定义的合法表名,再拼接到 ${} 中。绝不能直接使用用户输入。

二、MyBatis 配置层面的加固建议

除了正确使用占位符,还可以从配置和代码层面增加防线:

  • 开启 logPrefix 与 SQL 日志审计:记录最终执行的 SQL,便于发现异常拼接。
  • 使用 MyBatis-Plus 等增强工具时注意:其 QueryWrapperapply 方法若拼接字符串,同样可能引入注入。
  • 限制数据库账号权限:MyBatis 使用的数据库账号不应具有 DROPFILEEXECUTE 等高危权限。
  • 统一封装动态排序:提供 OrderByUtils,将前端传入的排序字段映射为白名单枚举,再拼接到 SQL。

三、延伸:XSS 的常见方式与前端防御

SQL 注入针对数据库,XSS 则针对浏览器。常见 XSS 方式包括:

  • 反射型:恶意脚本作为请求参数,服务器直接返回在页面中。
  • 存储型:恶意脚本被存入数据库,其他用户访问时触发。
  • DOM 型:前端 JavaScript 直接使用 innerHTMLdocument.write 等插入不可信数据。

前端防御手段:

  1. 输出编码:根据上下文对数据进行 HTML、URL、JavaScript 编码。
  2. 使用安全 API:用 textContent 代替 innerHTML,用 setAttribute 代替直接拼接。
  3. CSP(内容安全策略):限制脚本来源,禁止内联脚本。
  4. 输入验证:不依赖前端验证作为唯一防线,但可减少误操作。

四、MySQL 防止 SQL 注入的几种写法

在数据库层面,除了依赖预编译,还可以:

  • 使用 PREPARE 语句:MySQL 支持服务端预编译,但通常由驱动完成。
  • 严格模式与 NO_BACKSLASH_ESCAPES:避免转义绕过。
  • 最小权限原则:应用账号只授予 SELECTINSERTUPDATEDELETE 等必要权限。
  • 避免动态 SQL 拼接:存储过程内部也应使用参数化查询。
  • 使用 mysql_real_escape_string(PHP 场景):但这不是最佳实践,预编译才是。

五、Linux 服务器安全加固清单

Web 安全不止于应用层,服务器加固是最后一道屏障:

  1. 更新与补丁:定期更新内核、OpenSSL、MySQL、Tomcat 等。
  2. 最小化服务:关闭不必要的端口和服务,使用 netstatss 审查。
  3. SSH 加固:禁用 root 登录,使用密钥认证,修改默认端口,限制来源 IP。
  4. 防火墙:使用 iptablesfirewalld 只开放必要端口。
  5. 文件权限:Web 目录不可写,配置文件权限设为 600。
  6. 日志与监控:启用 auditd,集中收集日志,设置异常告警。
  7. 备份与恢复:定期备份数据库和关键配置,并演练恢复流程。
  8. WAF:部署 ModSecurity 等 Web 应用防火墙,拦截常见注入与 XSS 攻击。

六、总结

MyBatis 防 SQL 注入的核心只有一条:永远使用 #{},谨慎使用 ${},并对 ${} 的内容做白名单校验。误区往往源于对框架的过度信任和对动态 SQL 的随意拼接。将应用层、数据库层和服务器层的防护结合起来,才能有效抵御 SQL 注入、XSS 等常见 Web 威胁。安全不是某一个配置项,而是一套贯穿开发、部署、运维的实践习惯。

未经允许不得转载:任鹏个人博客 » MyBatis 中防止 SQL 注入的常见配置与误区

赞 (0) 打赏

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏