美文网首页Mybatis
mybatis如何预防不经意间的SQL注入

mybatis如何预防不经意间的SQL注入

作者: 小胖学编程 | 来源:发表于2021-12-10 15:50 被阅读0次

    SQL注入的危害就不多说,但是如何在日常开发中预防SQL注入?

    1. 理论

    1. 什么是SQL注入

    注入攻击的本质,是程序把用户输入的数据当做代码执行。这里有两个关键条件:
    第一是用户能够控制输入;
    第二是用户输入的数据被拼接到要执行的代码中从而被执行。

    sql注入漏洞则是程序将用户输入数据拼接到了sql语句中,从而攻击者即可构造、改变sql语义从而进行攻击。

    1. SQL漏洞一般的预防措施:
    1. 对于接受外部参数的动态SQL,能够进行预编译操作的地方一律使用预编译,禁止直接从字符串拼接SQL;
    2. 对于SQL不能预编译的地方,例如order by $param处,应该使用严格的白名单进行校验,然后拼接参数;
    1. mybatis动态sql的两种方式

    动态 sql 是 mybatis 的主要特性之一,在mybatis中我们可以把参数传到xml文件,由mybatis对sql及其语法进行解析,mybatis支持使用${}和#{}。

    #{}:在mybatis中是预编译操作;
    ${}:在mybatis中是直接拼接;

    1. 为什么#{}可以预发SQL注入

    直观的理由:

    使用${}方式传入的参数,mybatis不会对它进行特殊处理,而使用#{}传进来的参数,mybatis默认会将其当成字符串。

    例如:selec * from #{table};
    解析后:select * from "test";

    例如:selec * from ${table};
    解析后:select * from test;

    因为前者多了字符串的引号,那么可以预防sql注入。

    书面化的理由是:

    #和$在预编译处理中是不一样的。#类似jdbc中的PreparedStatement,对于传入的参数,在预处理阶段会使用?代替,待真正查询的时候,即在数据库管理系统中(DBMS)才会代入参数。而${}只是简单的替换。

    2. 实践

    2.1 一般sql的处理

    核心:能够进行预编译的地方,一律使用#{}进行预编译。

    在where接受参数:

        <select id="selectField">
            SELECT field_name FROM table_name WHERE 1 = 1
            <if test="condition != null">
                AND field_name = #{condtion} <!--禁止使用${param}拼接-->
            </if>
        </select>
    

    在like接受参数:使用CONCAT函数。

        <select id="selectByLike">
            SELECT field_name FROM table_name WHERE 1 = 1
            <if test="condition != null">
                AND field_name like CONCAT(#{condition}, '%') <!--禁止使${param}拼接-->
            </if>
        </select>
    

    在in处接受参数:

        <select id="selectInSQL">
            SELECT field_name FROM table_name WHERE 1 = 1
            <if test="conditionArray != null">
                field_name in
                <!--禁止使用${param}拼接-->
                <foreach collection="conditionArray" item="item"  open="(" close=")" separator=",">
                    #{item}
                </foreach>
            </if>
        </select>
    

    2.2 order by的处理

    核心:不能使用#{}进行预编译时,在mybatis进行白名单校验。

        <select id="sortSQL">
            SELECT field_name FROM table_name WHERE 1 = 1
            <!--传入的字段不为空,且传入的字段为name,才执行`order by name`的sql-->
            <if test="columnName != null and columnName=='name'.toString()"> 
                order by name
                <if test="orderName !=null and orderName=='desc'.toString()">
                    desc
                </if>
                <if test="orderName !=null and orderName=='asc'.toString()">
                    asc
                </if>
            </if>
        </select>
    
    实战.png

    文章参考

    mybatis中的#和$的区别

    相关文章

      网友评论

        本文标题:mybatis如何预防不经意间的SQL注入

        本文链接:https://www.haomeiwen.com/subject/unfnxrtx.html