PreparedStatement的用法与SQL注入分析

  表示预编译的 SQL 语句的对象。

  SQL 语句被预编译并存储在 PreparedStatement 对象中。然后可以使用此对象多次高效地执行该语句。

  Statement是PreparedStatement的父接口,不进行预编译操作,减少了进行预编译的开销.单次运行PreparedStatement要比Statement要慢一些.

  PreparedStatement可以实现Statement的所有功能,但是之所以叫它预编译指令,是因为在创建它的一个对象时可以给定具有一定格式的SQL字符串,然后用它的setXXX方法给指定的SQL语句以填空的方式赋值,具有这样的特性后,它在多次执行一条固定格式的字符串时就很方便,也更效率.不像Statement那样每次执行都要先编译字符串在执行SQL了.

  优点:

  1.   sql语句不是动态创建,可以有变量根据需要自定义SQL语句。 使用Statement 时就直接一句完整的SQL语句传参。

  2. 代码容易读,维护方便、例如:

  前者:采用Statement 方式,传参就是一句完整的SQL语句,书写 和 阅读令人很头疼。

  后者:采用PreparedStatement 预编译方式。 虽然代码多了几行了,但是阅读 修改是比较方便的。

  3. PreparedStatement 比Statement的性能更好

  数据库自己有种策略  :数据库编译器对预编译语句(例如Statement 和preparedstatement 创建的预编译语句)都有缓存策略,为了是在下一次的预编译语句具有相托相同语法匹配时直接执行不需要编译。 前者相匹配的机会大于后者的,因此在对预编语句的处理中 前者尽可能的提高了性能。

  4. PreparedStatement 更具有安全性,能防止SQL注入。

  SQL注入攻击是利用设计上的漏洞,在目标服务器上运行SQL语句进行攻击,动态生成SQL语句时没有对用户输入的数据进行验证是SQL注入攻击得逞的主要原因.

  对于JDBC而言,SQL注入攻击只对Statement有效,对PreparedStatement是无效的,这是因为PreparedStatement不允许在插入时改变查询的逻辑结构.

  ( 'amin'or'1'='1 这种巧妙改造SQL的方式,来绕过验证。 )绕过验证,但这种手段只对Statement有效,对PreparedStatement无效.因为PreparedStatement 指定了SQL的语法结构了,只是后者加某些变量。

  如果有一条SQL语句: "select * from 表 where 用户名 = '用户名'"

  Statement的SQL语句是这样写的: "select * from 表 where 用户名 = '"+ 变量值 +"'"

  PreparedStatement的SQL语句是这样写的: "select * from 表 where 用户名 = ?" 然后对应?赋值

  这样我们就发现输入 "aa' or '1' = '1"

  Statement是将这个和SQL语句做字符串连接到一起执行

  PreparedStatement是将 "aa' or '1' = '1" 作为一个字符串赋值给?,做为"用户名"字段的对应值,显然这样SQL注入无从谈起了.

 

发表评论

邮箱地址不会被公开。 必填项已用*标注