`
k1280000
  • 浏览: 203720 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

sql 注入 statement preparedstatement

    博客分类:
  • SQL
 
阅读更多

sql 注入原理 statement preparedstatement

 

http://blog.sina.com.cn/s/blog_6a384fce0100n95f.html

 

 

------以下转自 ikon.iteye.com/blog/1132255

一、我们先来看一下sql的执行过程:
在Oracle里执行一个SQL语句,一般都要经过下面几个步骤:
 Create a Cursor 创建游标;
 Parse the Statement 解析语句;
 Bind Any Variables 绑定变量;
 Run the Statement 运行语句;
 Close the Cursor 关闭游标;
如果是一个查询SQL,则还要经过下面的步骤:
 Describe Results of a Query 描述查询的结果集;
 Define Output of a Query 定义查询的输出数据;
 Fetch Rows of a Query 获取查询出来的行。

二、SQL解析过程
从上面的步骤可以看出,每执行一个SQL,都需要对它进行解析(Parse),而一个解析过程,需要完成下面的工作:
 语法检查,验证它是否是合法的语句,有没有语法错误;
 语义检查,实现数据字典的查找,以验证是否符合表和列的定义,类型是否正确;
 (如果是CBO优化模式,关于CBO,请看后面Oracle的优化器一章)收集参考对象的统计;
 在所要求的对象上获取语法分析锁,使得在语句的语法分析过程中不改变这些对象的定义;
 检查用户的权限是否足够;
 从许多可能的执行路径中选择此语句最佳的执行计划;
 将它装入共享SQL区;
 生成语句的编译版本(P-CODE)。
解析是一个昂贵的操作,因为解析过程中需要消耗许多资源,而且费时,正因为如此,Oracle创造了共享池的概念,共享池会自动将解析过的SQL缓存起来,以后碰到相同的SQL,就不用再解析了,这样可以大大提高SQL的执行速度。

三、 缓存SQL的原理
ORACLE执行SQL语句时,先将SQL语句的字串通过一个hash算法得出一个hash值,然后检查共享池中是否已存在这个哈希值,若有就用已缓存的执行计划来执行这个语句(即缓存命中,后面我们会提到共享池的命中率,就是这个概念),若没有(即缓存缺失)则需进行解析。
由于Oracle是通过SQL字符的hash值来判断是否为相同的SQL语句,因此,如果你的SQL有一点小小的变换,在Oracle看来,就是另外一个SQL了,会对它进行重新解析。
例如:

  1. select id, name from members where id = 1403   
  2. select id, name From members where id = 1403   
  3. select name, id from members where id = 1403  

这三条SQL在Oracle看来就是三条不同的SQL。

 绑定变量

在大部分时候,sql语句里有一些经常会变化的值。例如:

  1. select id, name from members where id = 1207   
  2. select id, name from members where id = 1208   
  3. select id, name from members where id = 1209  

前面说过了,这样的SQL其实是三条不同的SQL,因为它们的字符明显不一样。那我们该怎么样才能让它们成为同一条SQL呢?可以通过绑定变量来实现。
下面是一条含绑定变量的sql 语句:

  1. select id, name from members where id = :member_id  

这样不管member_id如何变化,Oracle都会认为这条SQL是同一条,就可以节省解析的成本了。
那么,在java开发中,怎么使用绑定变量呢?注意,不要认为下面的代码是在使用绑定变量:

  1. Statement stmt=conn.createStatement();   
  2. String member_id=member.id;   
  3. String sql="select id,name from members where id ="+member_id;   
  4. stmt.executeQuery(sql);  

上面的例子里,当member.id的值为1207时,我们传给stmt的SQL实际上是:

  1. select id, name from members where id = 1207  

当member.id的值为1208时,就是:

  1. select id, name from members where id = 1208  

它们在Oracle看来仍然是不同的SQL。
其实,在java中使用绑定变量非常简单,只需要使用PreparedStatement对象就可以了。如下:

  1. String sql="select id,name from members where id =?";   
  2. PreparedStatement pstmt=conn.createStatement(sql);   
  3. pstmt.setString(1,member.id);//将member.id传给第一个问号。  

这样,PreparedStatement会自动把这条SQL在传给Oracle时转化为类似下面的SQL:

  1. select id, name from members where id = :member_id  

这样就实现了绑定变量,它只需解析一次,不管member.id如何变化,都不用再做解析了。

 

分享到:
评论

相关推荐

    【IT十八掌徐培成】Java基础第23天-02.sql注入-preparedstatement-批量插入.zip

    在IT领域,尤其是在Java编程中,SQL注入是一个重要的安全问题,而PreparedStatement是解决这一问题的有效手段之一。批量插入则是提高数据库操作效率的关键技术。今天我们就来深入探讨这些知识点。 首先,我们来理解...

    【IT十八掌徐培成】Java基础第23天-02.sql注入-preparedstatement-批量插入 - 副本.zip

    在IT领域,尤其是在Java编程中,SQL注入是一个重要的安全问题,而PreparedStatement是解决这一问题的有效手段之一。批量插入则是提高数据库操作效率的关键技术。今天我们将深入探讨这两个知识点。 首先,让我们来...

    Statement和PreparedStatement之间的区别

    Statement和PreparedStatement之间的区别 Statement和PreparedStatement...结论:在 JDBC 应用中,建议使用PreparedStatement对象来代替Statement对象,以提高执行速度、避免SQL注入攻击和提高代码可读性和可维护性。

    如何获得PreparedStatement最终执行的sql语句

    当我们处理大量重复的SQL操作时,使用`PreparedStatement`可以避免SQL注入等问题,同时提升性能。这篇博客可能是探讨如何在实际运行中获取`PreparedStatement`最终执行的SQL语句,这对于调试和分析数据库操作非常有...

    Java防止SQL注入的几个途径

    如果使用 PreparedStatement 来代替 Statement 来执行 SQL 语句,其后只是输入参数,SQL 注入攻击手段将无效。这是因为 PreparedStatement 不允许在不同的插入时间改变查询的逻辑结构,大部分的 SQL 注入已经挡住了...

    SQL注入源码+SQL注入命令

    正确的方法是使用参数化查询,例如预编译的`PreparedStatement`,以防止SQL注入: ```java String sql = "SELECT * FROM users WHERE id=?"; PreparedStatement pstmt = connection.prepareStatement(sql); pstmt....

    如何解决sql注入问题

    Java开发人员使用JDBC(Java Database Connectivity)连接到Oracle数据库时,应该优先使用`PreparedStatement`和`CallableStatement`,而不是`Statement`。这是因为前两者提供了参数化查询的支持,能够有效抵御SQL...

    防止sql注入解决方案

    SQL注入是一种常见的网络安全威胁,它允许攻击者通过输入恶意的SQL代码来操纵数据库,获取、修改或删除敏感数据。为了防止SQL注入,开发者需要采取一系列的预防措施,确保应用程序的安全性。以下是一些核心的解决...

    java防止SQL注入

    PreparedStatement preState = conn.prepareStatement(sql); preState.setString(1, userName); preState.setString(2, password); ResultSet rs = preState.executeQuery(); 2. 采用正则表达式 可以使用正则表达式...

    防止sql注入demo

    - 使用预编译语句(PreparedStatement):这是防止SQL注入最常用的方法。预编译语句会将用户输入与SQL语句分离,确保即使输入含有恶意代码,也不会被执行。例如: ```java String query = "SELECT * FROM users ...

    如何防止sql注入【转载】

    例如,使用 PreparedStatement 代替 Statement,可以避免 SQL 注入攻击。预编译语句还可以提高性能和可维护性。 其次,使用正则表达式可以检测 SQL meta-characters,从而防止恶意代码的注入。例如,可以使用正则...

    Jsp防SQL注入

    某些数据库系统(如MySQL的`PREPARE STATEMENT`)提供了内置的SQL注入防护。同时,可以使用安全中间件如OWASP Java Encoder库来转义HTML、JavaScript和SQL等特殊字符。 ### 6. 避免硬编码SQL 尽量避免在JSP页面中...

    Java-JDBC【源码】JDBC概述、获取连接、SQL注入问题与解决、查询解析

    Java-JDBC【之】JDBC概述、获取连接、SQL注入问题与解决、查询...3.SQL注入问题与解决(Statement 、PreparedStatement) 3.1.模拟SQL注入 3.2.PreparedStatement解决 3.3.Statement 与 PreparedStatement 4.完整源码

    web安全之sql注入

    在实际开发过程中,如果使用普通的`Statement`来执行SQL语句,由于其直接拼接字符串的方式,很容易受到SQL注入的攻击。而`PreparedStatement`则通过预编译SQL语句并在执行时动态填充参数的方式来避免这一问题。这种...

    SQL注入+JSP+HTML+JavaBean

    1. **预编译SQL(PreparedStatement)**:使用PreparedStatement可以有效地防止SQL注入,因为它自动转义特殊字符,例如: ```java String username = request.getParameter("username"); PreparedStatement pstmt...

    4、SQL注入漏洞pdf资料

    PreparedStatement pstmt = conn.prepareStatement("SELECT * from users WHERE username=?"); pstmt.setString(1, username); ``` 七、SQL注入的检测 要检测SQL注入,需要对Web应用程序的日志进行分析,检查是否...

    SQL注入源码

    1. **预编译语句(PreparedStatement)**:使用PreparedStatement可以有效地防止SQL注入,因为它会将用户输入的数据作为参数处理,而不是直接拼接到SQL语句中。例如: ```java String sql = "SELECT * FROM users ...

    jsp 防止sql注入jsp 防止sql注入

    使用预编译的SQL语句(例如PreparedStatement)是防止SQL注入的最佳实践。这种方式将SQL语句与用户输入的数据分离,确保即使用户输入恶意代码,也不会影响到查询结构。例如: ```java String query = "SELECT * ...

    JSP如何防范SQL注入攻击

    ### JSP如何防范SQL注入攻击 #### 背景介绍 在进行Web开发的过程中,安全性是不容忽视的重要一环。特别是在使用动态语言如Java Server Pages (JSP)时,开发者必须时刻警惕各种潜在的安全威胁,其中SQL注入是最常见...

    SQL注入与代码防御.pdf

    在 Java 语言中,可以使用 PreparedStatement 对象来防御 SQL 注入攻击。例如: ```java String sql = "SELECT * FROM users WHERE username = ? and password = ?"; PreparedStatement pstmt = conn.prepare...

Global site tag (gtag.js) - Google Analytics