MyBatis的`${}`和`#{}`的区别及SQL防注入的方法-阿里云开发者社区

开发者社区> waylau> 正文

MyBatis的`${}`和`#{}`的区别及SQL防注入的方法

简介: 本文介绍了MyBatis的`${}`和`#{}`的用法区别,以及针对$可能带来的风险提供一种简易的SQL防注入的方法。
+关注继续查看

本文介绍了MyBatis的${}#{}的用法区别,以及针对$可能带来的风险提供一种简易的SQL防注入的方法。

#{}用法

select语句是MyBatis中最常用的元素之一,例如:

<select id="selectPerson" parameterType="int" resultType="hashmap">

SELECT * FROM PERSON WHERE ID = #{id}

</select>

此语句称为selectPerson,采用int(或Integer)类型的参数,并将查询结果封装为HashMap作为返回。

语句中#{id}这告诉MyBatis创建一个PreparedStatement参数。对于JDBC而言,这样的参数类似于PreparedStatement语句中的“?”标识,如下:

// JDBC代码
String selectPerson = "SELECT * FROM PERSON WHERE ID=?";

PreparedStatement ps = conn.prepareStatement(selectPerson);
ps.setInt(1,id);

${}用法

默认情况下,使用#{}语法将导致MyBatis生成PreparedStatement属性,并根据PreparedStatement参数安全地设置值(例如“?”标识)。虽然这更安全、更快,而且几乎总是首选,但有时只是想直接将未修改的字符串注入SQL语句。例如,对于订单排序,可以使用类似的内容:

ORDER BY ${columnName}

在上面的用法中,MyBatis不会修改或转义字符串。

但需要注意的是: ${}用法如果是直接接受用户的输入,将未经修改的语句注入到程序是不安全的。这将导致潜在的SQL注入攻击风险。

针对${}的SQL防注入器

${}用法存在SQL注入的风险,因此需要对用户的输入内容进行校验。这里提供一个简易的SQL防注入的方法。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * SQL注入防护器
 *
 * @author waylau.com
 * @since 2021-04-18
 */
public class SqlInjectionProtector {
    private static final String SPECIAL_CHAR = "\\W";

    /**
     * 校验SQL语句是否合法
     * 如果非法,则抛出异常
     *
     * @param statement 语句
     * @return 是否合法
     * @throws IllegalArgumentException 校验非法则抛出此异常
     */
    public static boolean verifySqLStatement(String statement) {
        if (!StringUtility.isEmpty(statement)) {
            if (isSpecialChar(statement)) {
                throw new IllegalArgumentException("illegal statement: " + statement);
            }
        }

        return Boolean.TRUE;
    }

    /**
     * 判断是否含有特殊字符
     *
     * @param str 校验的字符串
     * @return 是否特殊字符
     */
    public static boolean isSpecialChar(String str) {
        Pattern pattern = Pattern.compile(SPECIAL_CHAR);
        Matcher matcher = pattern.matcher(str);
        return matcher.find();
    }

}

上述代码核心思想是,通过正则表达式的方式,来检测出特殊字符。有特殊字符,就抛出异常,中断程序继续往下运行。

何为特殊字符?针对ORDER BY ${columnName} 这个例子而言,字段名的所使用的字符是有一定限制的,限制只能使用[a-z0-9A-Z_]这个范围内的字符。因此超出这个范围内的所有字符,即为特殊字符。在正则表达式里面,非[a-z0-9A-Z_]范围内的字符,可以用“\W”表示。

以下是测试用例

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

/**
* SqlInjectionProtector Test
*
* @author waylau.com
* @since 2021-04-18
*/
public class SqlInjectionProtectorTest {

    @Test
    public void testIsSpecialChar() {
        assertFalse(SqlInjectionProtector.isSpecialChar("user_name"));
        assertTrue(SqlInjectionProtector.isSpecialChar("user_name!"));
        assertTrue(SqlInjectionProtector.isSpecialChar("user_name@"));
        assertTrue(SqlInjectionProtector.isSpecialChar("user_name^"));
        assertTrue(SqlInjectionProtector.isSpecialChar("user_name ")); // 空格
        assertTrue(SqlInjectionProtector.isSpecialChar("insert\ninto\nuser_t")); // 换行符
        assertTrue(SqlInjectionProtector.isSpecialChar("user_name|user_t"));
    }

    @Test
    public void testVerifySqLStatement() {
        assertTrue(SqlInjectionProtector.verifySqLStatement("user_name"));
    }
}

参考引用

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
9421 0
java编程学习笔记——mybatis SQL注入问题
 SQL 注入攻击   首先了解下概念,什么叫SQL 注入:   SQL注入攻击,简称SQL攻击或注入攻击,是发生于应用程序之数据库层的安全漏洞。
1251 0
阿里云服务器安全组设置内网互通的方法
虽然0.0.0.0/0使用非常方便,但是发现很多同学使用它来做内网互通,这是有安全风险的,实例有可能会在经典网络被内网IP访问到。下面介绍一下四种安全的内网互联设置方法。 购买前请先:领取阿里云幸运券,有很多优惠,可到下文中领取。
11785 0
mybatis是如何防止SQL注入的
mybatis是如何防止SQL注入的 SQL注入是一种很简单的攻击手段,但直到今天仍然十分常见。究其原因不外乎:No patch for stupid。为什么这么说,下面就以JAVA为例进行说明: 假设数据库中存在这样的表:     table user( id varchar(20).
1524 0
MyBatis的`${}`和`#{}`的区别及SQL防注入的方法
本文介绍了MyBatis的`${}`和`#{}`的用法区别,以及针对$可能带来的风险提供一种简易的SQL防注入的方法。
281 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
11489 0
MyBatis中$和#的区别
动态 SQL 是 mybatis 的强大特性之一,也是它优于其他 ORM 框架的一个重要原因。mybatis 在对 sql 语句进行预编译之前,会对 sql 进行动态解析,解析为一个 BoundSql 对象,也是在此处对动态 SQL 进行处理的。
701 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
6876 0
MyBatis 中 ResultType 和 ResultMap 的区别 & mybatis 中 mapUnderscoreToCamelCase自动驼峰命名转换
使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。 如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。
3161 0
+关注
waylau
大道至简! https://waylau.com/
238
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载