MyBatis 中拼接字符串的几种方式

2024-05-21 21:17:31 浏览数 (2)

在 MyBatis 中,拼接字符串有以下几种方式:

使用 号进行拼接。

例如:

代码语言:javascript复制
SELECT * FROM users WHERE id = 1   2;

在 SQL 语句中, 号用于进行字符串拼接,相当于将两个字符串连接在一起。在上面的 SQL 语句中,1 和 2 会先进行数值运算,然后再拼接成字符串,最终的 SQL 语句等价于:

代码语言:javascript复制
SELECT * FROM users WHERE id = 3;

使用 CONCAT 函数进行拼接。

例如:

代码语言:javascript复制
SELECT * FROM users WHERE name = CONCAT('a', 'b');

在 SQL 语句中,CONCAT 函数用于将多个字符串拼接在一起,相当于 号的功能。在上面的 SQL 语句中,CONCAT 函数接收了两个参数,分别为 'a' 和 'b',最终会将它们拼接成 'ab',最终的 SQL 语句等价于:

代码语言:javascript复制
SELECT * FROM users WHERE name = 'ab';

使用 || 运算符进行拼接

例如:

代码语言:javascript复制
SELECT * FROM users WHERE name = 'a' || 'b';

在 SQL 语句中,|| 运算符用于将两个字符串拼接在一起,它的作用与 号和 CONCAT 函数类似。在上面的 SQL 语句中,两个字符串 'a' 和 'b' 会被拼接在一起,最终的 SQL 语句等价于:

代码语言:javascript复制
SELECT * FROM users WHERE name = 'ab';

使用 $ 符号

在 MyBatis 中,拼接字符串还可以使用 $ 符号。例如:

代码语言:javascript复制
SELECT * FROM users WHERE name = $name;

在 SQL 语句中, 符号用于指定一个字符串拼接,它会在 SQL 语句被执行前进行拼接。与 # 符号不同, 符号不会对输入值进行任何检查和转义,因此它可能会导致 SQL 注入攻击。在上面的 SQL 语句中,name将被拼接到SQL语句中,如果name 将被拼接到 SQL 语句中,如果 name将被拼接到SQL语句中,如果name 的值为 'ab',则最终的 SQL 语句为:

代码语言:javascript复制
SELECT * FROM users WHERE name = 'ab';

在使用 MyBatis 拼接字符串时,建议使用 号、CONCAT 函数或 || 运算符,避免使用 $ 符号,以免导致 SQL 注入攻击。

# 和 $ 符号

# 符号

# 用于指定一个占位符,它会在 SQL 语句被执行前进行替换。在下面的 SQL 语句中,#{id} 将被替换为实际的 id 值:

代码语言:javascript复制
SELECT * FROM users WHERE id = #{id};

如果 #{id} 的值为 1,则最终的 SQL 语句为:

代码语言:javascript复制
SELECT * FROM users WHERE id = 1;

$ 符号

符号用于指定一个字符串拼接,它会在 SQL 语句被执行前进行拼接。与 # 符号不同, 符号不会对输入值进行任何检查和转义,因此它可能会导致 SQL 注入攻击。例如,在下面的 SQL 语句中,$id 将被拼接到 SQL 语句中:

代码语言:javascript复制
SELECT * FROM users WHERE id = ${id};

同样如果 $id 的值为 1,则最终的 SQL 语句为

代码语言:javascript复制
SELECT * FROM users WHERE id = 1;

咋一看两者是一样的,那为什么推荐使用 # 符号呢?

区别 —— sql注入风险

代码语言:javascript复制
String sql = "SELECT * FROM users WHERE name = #{name}";

Map<String, Object> params = new HashMap<>();
params.put("name", "a' or '1' = '1");

// 执行 SQL 语句
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> users = sqlSession.selectList(sql, params);

在执行上面的代码时,MyBatis 会将 #{name} 替换为参数映射中的值,最终的 SQL 语句为:

代码语言:javascript复制
SELECT * FROM users WHERE name = 'a' or '1' = '1';

由于 # 符号会将参数值转义,因此它可以有效防止 SQL 注入攻击。

而 符号仅用于指定一个字符串拼接,它会在 SQL 语句被执行前进行拼接。与 # 符号不同, 符号不会对输入值进行任何检查和转义,因此它可能会导致 SQL 注入攻击。

代码语言:javascript复制
// 使用 $ 符号拼接字符串
String sql = "SELECT * FROM users WHERE name = ${name}";

Map<String, Object> params = new HashMap<>();
params.put("name", "a' or '1' = '1");

// 执行 SQL 语句
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> users = sqlSession.selectList(sql, params);

例如,在同样的 SQL 语句中,name将被拼接到SQL语句中,如果{name} 将被拼接到 SQL 语句中,如果 name将被拼接到SQL语句中,如果{name} 的值为 "a' or '1' = '1",则最终的 SQL 语句为:

代码语言:javascript复制
SELECT * FROM users WHERE name = a' or '1' = '1;

我们可以看到,拼接后没有带上引号;并且没有对 {name} 的值 "a' or '1' = '1" 进行转义。这可能恶意的sql注入发生。因此,建议使用 # 符号来指定占位符,而不是 符号来拼接字符串。

0 人点赞