【问题标题】:Mybatis mix prepared statement with sql injectionMybatis 混合预处理语句和 sql 注入
【发布时间】:2021-06-21 12:34:07
【问题描述】:

我有一个查询,我希望 Mybatis 将它的一部分视为 sql 注入,也可以视为准备好的语句。我使用的是 Mybatis xml 文件而不是注释。这就是我想要做的......

我的 java 对象正在传递一个包含 processId 和开始和结束日期的参数映射。 processId 是 WHERE 子句之前查询“顶部”的一部分。开始和结束日期在 WHERE 子句中。所以我试图获得作为准备好的语句运行的好处,但直到运行时我才知道 processId。我的 sql 如下所示,但不确定如何将这两种构建 sql 的模式混合在一起。有什么办法可以做到吗?

   SELECT ${processId}, x, y, z FROM AnotherTable t
     WHERE t.startDate >= ? AND t.endDate <= ?```

【问题讨论】:

    标签: prepared-statement sql-injection mybatis code-injection


    【解决方案1】:

    我找到了答案。我只需要在我的插入标签中指定参数类型和参数映射属性...

    <parameterMap type="java.util.Map" id="myParameterMap">
        <parameter property="startDate"/>
        <parameter property="endDate"/>
      </parameterMap>
    
      <insert  id="theSqlToRun" parameterType="java.util.Map" parameterMap="myParameterMap">
    SELECT ${processId}, x, y, z FROM AnotherTable t
         WHERE t.startDate >= ? AND t.endDate <= ?
    </insert>
    

    【讨论】:

    • 那是因为您决定不命名第二个和第三个参数,而是使用?(位置参数)。我建议不要这样做(并将它们命名为#{startDate}#{endDate}),因为将来修改 SQL 语句时很容易出错。
    • doc 中所述,&lt;parameterMap /&gt; 已弃用。没有需要它的功能。不清楚processId在SQL语句中是用作常量值还是列名。如果它是一个常数值,@TheImpaler 的答案是正确的。如果processId 是列名,则@TheImpaler 的上述评论是正确的解决方案。
    【解决方案2】:

    您不需要 SQL 注入(如${a})。普通参数(如#{a})将起作用。你没有提到具体的数据库,但据我记得所有 JDBC 驱动程序我都在“选择列表”中尝试过支持参数。

    你可以这样做:

    <select id="mySelect">
      select #{processId}, x, y, z 
      from AnotherTable t
      where t.startDate >= #{startDate} AND t.endDate &lt;= #{endDate}
    </select>
    

    记得如上所示转义你的&lt;

    【讨论】:

    • 谢谢穿刺者。看起来我可以使用 ${processId} 以及 #{startDate} 和 #{endDate} 来混合“statement”和“prepared statement”,并按预期工作。
    • 是的,您可以这样做,但除非绝对必要,否则最好避免 SQL 注入。下一个修改应用程序的开发人员可能不会像您那样小心,并且可能会在应用程序中打开一个很大的安全漏洞。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    • 2010-09-23
    • 2015-05-24
    相关资源
    最近更新 更多