#{} 于 ${} 的区别
我们讨论的占位符通常出现在MyBatis这样的持久层框架中。在MyBatis中,有两种常见的占位符:#{}和${}。它们有本质的区别,特别是在安全方面。
1. #{}(井号占位符)
原理:使用
#{}时,MyBatis会创建预编译语句(PreparedStatement),并将参数安全地设置到SQL中。它会将参数值作为字符串处理,并自动进行转义,从而防止SQL注入。示例:
xml
<select id="selectUser" resultType="User"> SELECT * FROM users WHERE username = #{username} AND password = #{password} </select>生成的SQL类似于:
sql
SELECT * FROM users WHERE username = ? AND password = ?然后通过PreparedStatement的set方法安全地设置参数。
安全性:由于使用了预编译,用户输入的值不会被解析为SQL代码,因此非常安全,可以防止SQL注入。
2. ${}(美元占位符)
原理:使用
${}时,MyBatis会直接将参数值替换到SQL语句中,是简单的字符串拼接。不会进行转义,也不会使用预编译。示例:
xml
<select id="selectUser" resultType="User"> SELECT * FROM users WHERE username = '${username}' AND password = '${password}' </select>如果username输入
admin,password输入' OR '1'='1,那么生成的SQL将是:sql
SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1'这就会导致SQL注入。
用途:
${}通常用于动态指定表名、列名等无法使用预编译的地方,比如:xml
<select id="selectUser" resultType="User"> SELECT * FROM ${tableName} WHERE id = #{id} </select>但即使这样,也需要非常小心,因为如果表名是用户输入的,那么同样存在风险(虽然不是SQL注入,但可能导致其他问题,如查询非法的表)。
总结
安全性:
#{}是安全的,可以防止SQL注入;${}是不安全的,容易导致SQL注入。使用场景:
绝大多数情况下,尤其是对于用户输入的值,必须使用
#{}。只有在需要动态指定表名、列名等SQL关键字时,才考虑使用
${},并且必须确保这些值不是来自用户输入,或者经过严格的校验。
所以,在编写MyBatis的SQL映射时,一定要谨慎使用${},对于用户输入的参数,必须使用#{}。
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 程序员阿政
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果