zoukankan      html  css  js  c++  java
  • mybatis中#{}与${}区别

    mybatis 中使用 sqlMap 进行 sql 查询时,经常需要动态传递参数,例如sql 如下:

    select * from student where uid=#{uid} AND student_name='${studentName}'

    在动态 SQL 解析阶段, #{ } 和 ${ } 会有不同的表现:

    #{ } 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符占位符 ?。

    上面的例子就被解析为

    ...... uid=? 

    ${ } 仅仅为一个纯碎的 string 替换,在mybatis的动态 SQL 解析阶段将会进行变量替换。比如:传入的studentName参数是“张三”

    ...... student_name='张三'

    最后解析完成的完整语句就是

    select * from student where uid= ? AND student_name='张三'

    然后把解析好的语句在通过JDBC执行。

    所以因为在${ } 在预编译之前已经被变量替换了,这会存在 sql 注入问题。比如:传入的studentName参数是“1' OR '1'='1

    在mybatis中解析完成后变成了

    select * from student where uid= ? AND student_name='1' OR '1'='1'

    这样就查询出所有的数据了。

    源码查看:

    在执行mybtis的查询是,会执行到PreparedStatementHandler#query,查看生成的PreparedStatement

     如果传入参数传入的studentName参数是“1' OR '1'='1

     所以就出现注入的情况了。

    如果我们把${studentName}换成#{studentName},在传入“1' OR '1'='1”呢

    在mybatis解析出的结果

     在数据库的执行日志中查询执行的sql语句

     发现我们传入的“'”被转义了,

     所以通过预编译,用占位符的方式传值可以把一些特殊的字符进行转义,这样可以防止一些sql注入。

    其原因就是:采用了JDBC的PreparedStatement,就会将sql语句:“select * from student where uid= ? AND student_name= ?” 预先编译好,也就是SQL引擎会预先进行语法分析,产生语法树,生成执行计划,也就是说,后面你输入的参数,无论你输入的是什么,都不会影响该SQL语句的语法结构了,因为语法分析已经完成了,而语法分析主要是分析sql命令,比如select,from,where,and,or,order by等等。所以即使你后面输入了这些sql命令,也不会被当成sql命令来执行了,因为这些SQL命令的执行,必须先得通过语法分析,生成执行计划,既然语法分析已经完成,已经预编译过了,那么后面输入的参数,是绝对不可能作为SQL命令来执行的,只会被当做字符串字面值参数。所以的sql语句预编译可以防御SQL注入。而且在多次执行同一个SQL时,能够提高效率。原因是SQL已编译好,再次执行时无需再编译。

    默认使用PreparedStatement是不能执行预编译的,这需要在url中给出useServerPrepStmts=true参数(MySQL Server 4.1之前的版本是不支持预编译的,而Connector/J在5.0.5以后的版本,默认是没有开启预编译功能的)。
    例如:jdbc:mysql://localhost:3306/test?useServerPrepStmts=true
    这样才能保证mysql驱动会先把SQL语句发送给服务器进行预编译,然后在执行executeQuery()时只是把参数发送给服务器。
  • 相关阅读:
    php文件hash算法,秒传原理
    pytest-2:allure 的安装、使用
    python操作数据库(Mysql)
    python中OS常用方法
    Selenium2+python-unittest之装饰器(@classmethod)
    selenium中嵌套iframe的切换
    selenium3驱动IE浏览器设置
    selenium测试报告(含通过率统计图和失败截图)
    python3打包成exe---pyinstaller方法
    Python2图像文本识别
  • 原文地址:https://www.cnblogs.com/grasp/p/11857800.html
Copyright © 2011-2022 走看看