• 为什么参数化查询可以防止SQL注入?(转)


     
    昨天被某大牛问了一个问题,为什么SQL参数化查询可以防止SQL注入,参数化查询的原理是什么? 结果闷逼了,之前只知道参数化查询是可以防止SQL注入,但是没有深究其原理,今天就找一些文章,学习一下,也分享给大家。

    以下引用知乎大神们的回答:

    原理是采用了预编译的方法,先将SQL语句中可被客户端控制的参数集进行编译,生成对应的临时变量集,再使用对应的设置方法,为临时变量集里面的元素进行赋值,赋值函数setString(),会对传入的参数进行强制类型检查和安全检查,所以就避免了SQL注入的产生。
    最近在深入学习Java,附上一段实现代码,其他语言把赋值函数的处理封装起来了,导致用户不可见,不能了解其中的机理。
    import java.sql.PreparedStatement;
     
    String sql = "select * from user where username=? and passwd=?";
    ps = conn.PreparedStatement(sql);
    ps.setString(1, "admin");
    ps.setString(2, "123456");
    resultSet = ps.executeQuery();
    具体实现代码参考 Java 的 PreparedStatement (Java Platform SE 7 ) ,其它语言可以对照他的原理进行实现。
    参数查询是数据库原生提供的能力,而不是ado.net等数据访问类库提供的,后者只是对前者的封装。我们在程序语言中写的sql语句和参数对象,送到数据库时还是语句和参数,并不是有些答案认为的那样把参数的值转好义后拼接进语句,最后把语句提给数据库。要说类库做了什么“预处理”,大概只是在开发者没有显式指定参数的类型和长度时,类库会根据参数的值自动为其确定合适的类型和长度,仅此而已。这一点用数据库语句跟踪工具(如SQL Server Profiler)很容易证实。所以参数化查询真不关程序语言/类库多少事。
    至于数据库接到语句和参数后如何处理,我的理解/猜测是,数据库负责解析查询语句的子系统将语句转换/编译为某种底层的、数据库执行子系统能executing的语言(好比C#编译器把C#编译为IL给CLR跑类似),就这一步,就将本批查询语句的语义固化成了一套行为动作,这套行为动作正是所谓的“执行计划”,执行计划描述的东西大概是从什么地方取数据、如何处理数据等等,这也是为什么表名、字段名不能参数化的原因,因为这些东西都不确定的话根本没法生成执行计划。至于参数的值有没有影响执行计划的生成,是有的,但它影响的是这个值能否命中某个索引、统计信息等性能相关的东西,能的话就生成更优的执行计划(精确指引到某个页取数据之类),否则走笨方法(如全表扫描),而不会对整套计划的纲领造成影响,这个就是参数化能防注入的原因所在。
    简单总结,参数化能防注入的原因在于,语句是语句,参数是参数,参数的值并不是语句的一部分,数据库只按语句的语义跑,至于跑的时候是带一个普通背包还是一个怪物,不会影响行进路线,无非跑的快点与慢点的区别。
  • 相关阅读:
    UI自动化测试(二)浏览器操作及对元素的定位方法(xpath定位和css定位详解)
    UI自动化测试(一)简介及Selenium工具的介绍和环境搭建
    接口测试——HttpClient工具的https请求、代理设置、请求头设置、获取状态码和响应头
    SpringBoot系列之JDBC数据访问
    Docker系列之MySQL安装教程
    Docker系列之常用命令操作手册
    Docker系列之原理简单介绍
    SpringBoot系列之集成jsp模板引擎
    SpringBoot源码学习系列之嵌入式Servlet容器
    SpringBoot源码学习系列之异常处理自动配置
  • 原文地址:https://www.cnblogs.com/manmanrenshenglu/p/9013079.html
Copyright © 2020-2023  润新知