• 精创网络
  • 精创网络
  • 首页
  • 产品优势
  • 产品价格
  • 产品功能
  • 关于我们
  • 在线客服
  • 登录
  • DDoS防御和CC防御
  • 精创网络云防护,专注于大流量DDoS防御和CC防御。可防止SQL注入,以及XSS等网站安全漏洞的利用。
  • 免费试用
  • 新闻中心
  • 关于我们
  • 资讯动态
  • 帮助文档
  • 白名单保护
  • 常见问题
  • 政策协议
  • 帮助文档
  • MyBatis中#与$的区别及其对SQL注入的影响
  • 来源:www.jcwlyf.com更新时间:2025-07-23
  • 在MyBatis框架的使用过程中,#和$是两个非常重要且容易混淆的符号。它们在SQL语句的拼接和执行中有着不同的作用,并且对SQL注入问题的影响也截然不同。本文将详细探讨MyBatis中#与$的区别以及它们对SQL注入的影响。

    一、#和$的基本概念

    在MyBatis里,#和$都用于在SQL语句中引用参数。当我们编写Mapper XML文件或者使用注解来定义SQL语句时,需要动态地传入参数,这时候就会用到这两个符号。

    ### #符号

    #符号是MyBatis中常用的参数占位符,它会将传入的参数进行预编译处理。在SQL语句执行之前,MyBatis会把#{}替换为一个占位符(通常是?),然后使用PreparedStatement来执行SQL语句,将参数值安全地设置到占位符中。

    以下是一个简单的示例,假设我们有一个查询用户信息的SQL语句:

    <select id="getUserById" parameterType="int" resultType="User">
        SELECT * FROM users WHERE id = #{id}
    </select>

    在这个例子中,#{id}会被替换为一个占位符,然后通过PreparedStatement将实际的id值设置到占位符中。

    ### $符号

    $符号则是直接将传入的参数值拼接到SQL语句中。MyBatis会直接把${}替换为传入的参数值,而不会进行预编译处理。

    同样以查询用户信息为例,使用$符号的SQL语句如下:

    <select id="getUserById" parameterType="int" resultType="User">
        SELECT * FROM users WHERE id = ${id}
    </select>

    在这个例子中,${id}会被直接替换为传入的id值,然后执行拼接好的SQL语句。

    二、#和$的区别

    ### 语法和使用方式

    #符号使用#{参数名}的形式,而$符号使用${参数名}的形式。这是它们最直观的区别。

    ### 预编译处理

    #符号会进行预编译处理,使用PreparedStatement来执行SQL语句。这种方式可以有效地防止SQL注入攻击,因为参数值是通过安全的方式设置到占位符中的,不会改变SQL语句的结构。

    而$符号不会进行预编译处理,它直接将参数值拼接到SQL语句中。这就意味着如果参数值包含恶意的SQL代码,就可能会改变SQL语句的结构,从而导致SQL注入攻击。

    ### 性能方面

    从性能角度来看,#符号使用PreparedStatement,由于PreparedStatement会对SQL语句进行预编译,当多次执行相同结构的SQL语句时,只需要编译一次,后续只需要设置不同的参数值即可,因此性能较高。

    而$符号每次都会重新拼接SQL语句,对于相同结构的SQL语句,每次执行都需要重新编译,性能相对较低。

    ### 适用场景

    #符号适用于大多数情况下的参数传递,特别是涉及到用户输入的参数,如查询条件、排序字段等。因为它可以保证数据的安全性。

    $符号适用于一些特殊场景,如动态表名、动态列名等。因为这些信息不能使用占位符来处理,只能通过拼接的方式将其添加到SQL语句中。

    以下是一个使用$符号处理动态表名的示例:

    <select id="getUserFromTable" parameterType="map" resultType="User">
        SELECT * FROM ${tableName} WHERE id = #{id}
    </select>

    在这个例子中,tableName使用$符号进行拼接,而id使用#符号进行参数传递。

    三、#和$对SQL注入的影响

    ### #符号对SQL注入的防护

    由于#符号使用PreparedStatement进行预编译处理,它可以有效地防止SQL注入攻击。PreparedStatement会将参数值和SQL语句分开处理,参数值会被安全地设置到占位符中,不会改变SQL语句的结构。

    例如,假设我们有一个登录验证的SQL语句:

    <select id="login" parameterType="map" resultType="User">
        SELECT * FROM users WHERE username = #{username} AND password = #{password}
    </select>

    如果用户输入的用户名和密码包含恶意的SQL代码,如' OR '1'='1,由于#符号的预编译处理,这些恶意代码会被当作普通的字符串处理,不会改变SQL语句的结构,从而避免了SQL注入攻击。

    ### $符号导致的SQL注入风险

    $符号直接将参数值拼接到SQL语句中,如果参数值包含恶意的SQL代码,就会改变SQL语句的结构,从而导致SQL注入攻击。

    还是以登录验证为例,使用$符号的SQL语句如下:

    <select id="login" parameterType="map" resultType="User">
        SELECT * FROM users WHERE username = ${username} AND password = ${password}
    </select>

    如果用户输入的用户名和密码包含恶意的SQL代码,如' OR '1'='1,那么拼接后的SQL语句就会变成:

    SELECT * FROM users WHERE username = ' OR '1'='1 AND password = ' OR '1'='1

    这个SQL语句会始终返回true,从而绕过了登录验证,造成了SQL注入攻击。

    四、如何正确使用#和$以避免SQL注入

    ### 优先使用#符号

    在大多数情况下,应该优先使用#符号来传递参数。特别是涉及到用户输入的参数,如查询条件、排序字段等,都应该使用#符号。这样可以保证数据的安全性,避免SQL注入攻击。

    ### 谨慎使用$符号

    当需要使用$符号时,如动态表名、动态列名等,一定要确保参数值的来源是可信的。可以通过白名单验证、正则表达式等方式对参数值进行过滤和验证,防止恶意的SQL代码注入。

    以下是一个对动态表名进行白名单验证的示例:

    public List<User> getUserFromTable(String tableName, int id) {
        List<String> allowedTables = Arrays.asList("users", "orders", "products");
        if (!allowedTables.contains(tableName)) {
            throw new IllegalArgumentException("Invalid table name");
        }
        Map<String, Object> params = new HashMap<>();
        params.put("tableName", tableName);
        params.put("id", id);
        return sqlSession.selectList("getUserFromTable", params);
    }

    在这个例子中,我们通过白名单验证的方式确保传入的表名是合法的,从而避免了SQL注入攻击。

    综上所述,MyBatis中的#和$符号在使用方式、预编译处理、性能和对SQL注入的影响等方面都存在明显的区别。在实际开发中,我们应该根据具体的场景正确使用这两个符号,优先使用#符号来保证数据的安全性,谨慎使用$符号并做好参数验证,以避免SQL注入攻击。

  • 关于我们
  • 关于我们
  • 服务条款
  • 隐私政策
  • 新闻中心
  • 资讯动态
  • 帮助文档
  • 网站地图
  • 服务指南
  • 购买流程
  • 白名单保护
  • 联系我们
  • QQ咨询:189292897
  • 电话咨询:16725561188
  • 服务时间:7*24小时
  • 电子邮箱:admin@jcwlyf.com
  • 微信咨询
  • Copyright © 2025 All Rights Reserved
  • 精创网络版权所有
  • 皖ICP备2022000252号
  • 皖公网安备34072202000275号