Mybatis中防止Sql注入

本文介绍了SQL注入,它是将恶意SQL插入执行字段以不正当操作数据库信息的技术,JDBC中用PreparedStatement可防注入。还阐述了MyBatis中防止SQL注入的方法,对比了#和$的区别,指出#可预编译处理,能很大程度防注入,最后进行了演示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、什么是Sql注入

sql注入是一种代码注入技术,将恶意的sql插入到被执行的字段中,以不正当的手段多数据库信息进行操作。

在jdbc中使用一般使用PreparedStatement就是为了防止sql注入。

比如代码 :"select * from user where id =" + id;
正常执行不会出现问题,一旦被sql注入,比如将传入参数id=“3 or 1 = 1”,那么sql会变成
"select * from user where id = 3 or 1 = 1",这样全部用户信息就一览无遗了。

二、MyBatis中防止sql注入

下面是Mybatis的两种sql。

  <select id="selectByPrimaryKey" resultMap="BaseResultMap"         
                        parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from user
    where id = #{id,jdbcType=INTEGER}
  </select>
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" 
                         parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from user
    where id = ${id,jdbcType=INTEGER}
  </select>

可以很清楚地看到,主要是#和$的区别。

# 将sql进行预编译"where id = ?",然后底层再使用PreparedStatement的set方法进行参数设置。

$ 将传入的数据直接将参数拼接在sql中,比如 “where id = 123”。

因此,#与$相比,#可以很大程度的防止sql注入,因为对sql做了预编译处理,因此在使用中一般使用#{}方式。

三、演示

在项目中配置log4j。方便查看sql日志。

#方式

查看日志,sql进行了预编译,使用了占位符,防止了sql注入。  
[cn.jxust.cms.dao.UserMapper.selectByPrimaryKey] - ==>  Preparing: select id, stuId, username, password, type, info from user where id = ? 
  [cn.jxust.cms.dao.UserMapper.selectByPrimaryKey] - ==> Parameters: 1(Integer)
  [cn.jxust.cms.dao.UserMapper.selectByPrimaryKey] - <==      Total: 1

$方式

$传入的数据直接显示在sql中
 [cn.jxust.cms.dao.UserMapper.selectByPrimaryKey] - ==>  Preparing: select id, stuId, username, password, type, info from user where id = 1 
  [cn.jxust.cms.dao.UserMapper.selectByPrimaryKey] - ==> Parameters: 
  [cn.jxust.cms.dao.UserMapper.selectByPrimaryKey] - <==      Total: 1

​

附:使用$方式时,需要在mapper接口中使用@Param注解。否则会报There is no getter for property named 'id' in 'class java.lang.Integer'错误

User selectByPrimaryKey(@Param(value = "id") Integer id);

 

参考资料:

https://www.cnblogs.com/mmzs/p/8398405.html

### MyBatis防止SQL注入的最佳实践 在MyBatis框架中,为了有效防止SQL注入攻击,开发者应遵循一系列最佳实践。以下是详细的说明: #### 1. 使用`#{}`占位符替代`${}` MyBatis中的`#{}`会被解析为JDBC的预编译参数(PreparedStatement),从而确保传递的参数被正确转义并作为独立的数据处理,而非SQL语句的一部分[^3]。 ```sql SELECT * FROM users WHERE username = #{username} ``` 这种方式能够显著降低SQL注入的风险,因为它不会将用户输入直接嵌入到SQL字符串中。 #### 2. 避免使用 `${}` 进行动态替换 尽管`${}`允许动态替换SQL片段,但它会将变量值直接插入到SQL语句中,而没有任何转义机制。因此,在使用`${}`时需格外小心,尤其是当涉及外部输入数据时[^2]。 如果确实需要使用`${}`来实现某些复杂功能,则应对传入的变量进行严格的校验和过滤[^1]。 #### 3. 输入参数校验 无论采用何种方式构建SQL语句,都应在应用层面对所有来自客户端的输入执行必要的验证逻辑。例如,对于用户名字段可限定长度范围以及字符集;针对整数型参数则强制转换成数值类型后再参与运算等操作。 #### 4. 权限管理与最小化原则 数据库账户应当仅授予完成特定任务所需的最低限度权限。即使存在潜在漏洞也无法造成更大破坏。 #### 5. 利用框架内置的安全特性 MyBatis 提供了一些额外选项帮助增强安全性。比如调整 `targetRuntime` 属性至更简单的模式 (`MyBatis3Simple`) 可减少因自定义过多而导致错误的可能性。 --- ### 参数化查询的具体使用方法 下面展示了一个完整的例子,演示如何利用 `#{}` 实现安全的参数绑定: 假设有一个需求是从表 `users` 查询指定名字对应的记录: ```xml <select id="selectUserByName" parameterType="string" resultType="User"> SELECT * FROM users WHERE name = #{name} </select> ``` 上述XML映射文件中的 `#{name}` 将由 MyBatis 自动转化为 PreparedStatement 的形式,并且任何特殊字符都会经过适当编码处理。 同样也可以通过 Java 接口调用来触发此 SQL 请求: ```java public interface UserMapper { List<User> selectUserByName(@Param("name") String name); } // 调用示例 List<User> users = userMapper.selectUserByName("John Doe"); ``` 以上代码片段展示了基于接口风格编程的方式访问数据库资源的同时保持了良好的防护措施。 --- ### 总结 综合运用上述提到的各种策略——优先选用 `#{}` 替代 `${}`、严格审查进入系统的每一个请求参数、合理分配DBMS用户的职能边界以及善加发挥现代ORM工具箱里的各种武器装备,就可以构筑起一道坚固防线抵御住绝大多数类型的SQL Injection威胁[^2]. ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值