`

SQL注入攻击例子及Statement和PreparedStatement的比较(转载)

阅读更多
SQL injection is a technique that exploits a security vulnerability occurring in the database layer of an application . The vulnerability is present when user input is either incorrectly filtered for string literal escape characters embedded in SQL statements or user input is not strongly typed and thereby unexpectedly executed. It is in fact an instance of a more general class of vulnerabilities that can occur whenever one programming or scripting language is embedded inside another.

 

Google翻译如下(20090331追加):

SQL注入是一种技术,利用一个安全漏洞发生在数据库层的应用程序。该漏洞存在时,用户输入的是不是正确过滤字符串转义字符中嵌入SQL语句或用户输入不强类型,从而出人意料地执行。事实上,它是一个实例一个更一般类别的安全漏洞,可能会发生时,一个编程或脚本语言是内嵌另一个。

 

 

SQL注入 攻 击 例子及 Statement和 PreparedStatement 的比 较



SQL注入 攻 击 是利用是指利用 设计 上的漏洞,在目 标 服 务 器上运行 Sql语 句以及 进 行其他方式的 攻 击 ,
动态 生成 Sql语 句 时 没有 对 用 户输 入的数据 进 行 验证 是 Sql注入 攻 击 得逞的主要原因。
对 于 JDBC而言, SQL注入 攻 击 只 对 Statement有效, 对 PreparedStatement 是无效的, 这 是因 为 PreparedStatement 不允 许 在不同的插入 时间 改 变查询 的 逻辑结 构。

如 验证 用 户 是否存在的 SQL语 句 为 :
select count(*) from usertable where name='用 户 名 ' and pswd='密 码 '
如果在 用 户 名字段 中 输 入 ' or '1'='1' or '1'='1
或是在 密 码 字段 中 输 入 1' or '1'='1
将 绕过验证 ,但 这种 手段只 对 只 对 Statement有效, 对 PreparedStatement 无效。




PreparedStatement 相 对 Statement有以下 优 点:

1.防注入 攻 击

2.多次运行速度快

3.防止 数据 库缓 冲区溢出

4.代 码 的可 读 性可 维护 性好



这 四点使得 PreparedStatement 成 为访问 数据 库 的 语 句 对 象的首 选 ,缺点是灵活性不 够 好,有些 场 合 还 是必 须 使用 Statement。

网上抄的:


1.PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程
2.使用 Statement 对象。在对数据库只执行一次性存取的时侯,用 Statement 对象进行处理。PreparedStatement 对象的开销比Statement大,对于一次性操作并不会带来额外的好处。
3.statement每次执行sql语句,相关数据库都要执行sql语句的编译,preparedstatement是预编译得,preparedstatement支持批处理
4.
Code Fragment 1:

String updateString = "UPDATE COFFEES SET SALES = 75 " + "WHERE COF_NAME LIKE ′Colombian′";
stmt.executeUpdate(updateString);

Code Fragment 2:

PreparedStatement updateSales = con.prepareStatement("UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");
updateSales.setInt(1, 75);
updateSales.setString(2, "Colombian");
updateSales.executeUpdate();

片断2和片断1的区别在于,后者使用了PreparedStatement对象,而前者是普通的Statement对象。 PreparedStatement对象不仅包含了SQL语句,而且大多数情况下这个语句已经被预编译过,因而当其执行时,只需DBMS运行SQL语句, 而不必先编译。当你需要执行Statement对象多次的时候,PreparedStatement对象将会大大降低运行时间,当然也加快了访问数据库的 速度。
这种转换也给你带来很大的便利,不必重复SQL语句的句法,而只需更改其中变量的值,便可重新执行SQL语句。选择PreparedStatement对 象与否,在于相同句法的SQL语句是否执行了多次,而且两次之间的差别仅仅是变量的不同。如果仅仅执行了一次的话,它应该和普通的对象毫无差异,体现不出 它预编译的优越性。
5.执行许多SQL语句的JDBC程序产生大量的Statement和PreparedStatement对象。通常认为 PreparedStatement对象比Statement对象更有效,特别是如果带有不同参数的同一SQL语句被多次执行的时候。 PreparedStatement对象允许数据库预编译SQL语句,这样在随后的运行中可以节省时间并增加代码的可读性。

然而,在Oracle环境中,开发人员实际上有更大的灵活性。当使用Statement或PreparedStatement对象时,Oracle数据库 会缓存SQL语句以便以后使用。在一些情况下,由于驱动器自身需要额外的处理和在Java应用程序和Oracle服务器间增加的网络活动,执行 PreparedStatement对象实际上会花更长的时间。

然而,除了缓冲的问题之外,至少还有一个更好的原因使我们在企业应用程序中更喜欢使用PreparedStatement对象,那就是安全性。传递给 PreparedStatement对象的参数可以被强制进行类型转换,使开发人员可以确保在插入或查询数据时与底层的数据库格式匹配。

当处理公共Web站点上的用户传来的数据的时候,安全性的问题就变得极为重要。传递给PreparedStatement的字符串参数会自动被驱动器忽 略。最简单的情况下,这就意味着当你的程序试着将字符串“D'Angelo”插入到VARCHAR2中时,该语句将不会识别第一个“,”,从而导致悲惨的 失败。几乎很少有必要创建你自己的字符串忽略代码。

在Web环境中,有恶意的用户会利用那些设计不完善的、不能正确处理字符串的应用程序。特别是在公共Web站点上,在没有首先通过 PreparedStatement对象处理的情况下,所有的用户输入都不应该传递给SQL语句。此外,在用户有机会修改SQL语句的地方,如HTML的 隐藏区域或一个查询字符串上,SQL语句都不应该被显示出来。
在执行SQL命令时,我们有二种选择:可以使用PreparedStatement对象,也可以使用Statement对象。无论多少次地使用同一个 SQL命令,PreparedStatement都只对它解析和编译一次。当使用Statement对象时,每次执行一个SQL命令时,都会对它进行解析 和编译。


第一:

prepareStatement会先初始化SQL,先把这个SQL提交到数据库中进行预处理,多次使用可提高效率。
createStatement不会初始化,没有预处理,没次都是从0开始执行SQL

第二:

prepareStatement可以替换变量
在SQL语句中可以包含?,可以用ps=conn.prepareStatement("select * from Cust where ID=?");
int sid=1001;
ps.setInt(1, sid);
rs = ps.executeQuery();
可以把?替换成变量。
而Statement只能用 int sid=1001;
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from Cust where ID="+sid);
来实现。

第三:

prepareStatement会先初始化SQL,先把这个SQL提交到数据库中进行预处理,多次使用可提高效率。
createStatement不会初始化,没有预处理,没次都是从0开始执行SQL
分享到:
评论

相关推荐

    java防止SQL注入

    Java 防止 SQL 注入是一个至关重要的安全问题,SQL 注入攻击是最常见的攻击方式之一,它不是利用操作系统或其他系统的漏洞来实现攻击的,而是程序员因为没有做好判断,被不法用户钻了 SQL 的空子。因此,在系统开发...

    PreparedStatement和Statement

    此外,`PreparedStatement`还支持参数化查询,这有助于防止SQL注入攻击,提高程序的安全性。 示例代码: ```java String sql = "INSERT INTO my_table (name, age) VALUES (?, ?)"; Connection conn = ...

    利用JDBC工具类的方式实现mysql数据库的连接并且完成登录相关功能(防sql注入方式)

    在本示例中,我们将探讨如何使用JDBC(Java Database Connectivity)工具类与MySQL数据库建立连接,并实现登录功能,同时重点介绍如何利用PreparedStatement防止SQL注入攻击。 首先,JDBC是Java语言访问数据库的...

    可注入SQL的代码、防止SQL注入

    下面是一个使用Java的JDBC进行数据库查询的例子,这个例子使用了参数化查询,从而有效防止SQL注入攻击: ```java String user = "your_username"; String pwd = "your_password"; String url = "jdbc:mysql://...

    Pr_St_insert.rar_statement

    - **不安全**: 如果SQL语句包含用户输入,直接使用Statement可能导致SQL注入攻击,因为Statement对象不会自动转义特殊字符。 - **效率低**: 每次执行Statement对象的SQL语句时,数据库都需要解析并编译该语句,这在...

    PreparedStatement详细用法

    - **防止SQL注入**:`PreparedStatement`通过参数化查询,确保了用户输入的数据不会被解释为SQL代码的一部分,从而有效防止了SQL注入攻击。 - **数据类型转换**:对于日期、时间等复杂数据类型的处理,`...

    JDBC基础教程之PreparedStatement.doc

    通过以上介绍可以看出,`PreparedStatement`不仅可以提高执行SQL语句的效率,还能有效防止SQL注入攻击,因为它使用参数化查询而非字符串拼接的方式构建SQL语句。因此,在开发涉及数据库操作的应用程序时,推荐优先...

    sql语句中用问号代替参数

    1. **防止SQL注入**:问号参数化能有效防止SQL注入攻击。因为它确保了用户输入的数据不会被解析为SQL代码,而是作为原始数据处理。即使用户尝试插入恶意SQL,数据库也会将它们视为普通字符串,而不会执行。 2. **...

    SQL语句填充占位符

    2. **防止SQL注入**:PreparedStatement会自动转义参数,有效防止恶意SQL注入攻击。 3. **易于维护**:静态SQL模板使得代码更清晰,易于理解和调试。 此外,还有一些第三方库,如MyBatis和Hibernate,提供了更高级...

    JDBC 连接到 SQL server 2005 数据库简单例子

    请注意,实际项目中应考虑使用`PreparedStatement`以防止SQL注入攻击,并且可以考虑使用连接池来管理数据库连接,提高性能和资源利用率。 总结起来,JDBC是Java与数据库交互的重要工具,通过它我们可以轻松地执行...

    java jdbc连接sql server的小例子

    此外,还可以使用PreparedStatement来插入数据,这可以防止SQL注入攻击: ```java String insertSql = "INSERT INTO Employees (ID, NAME, AGE, ADDRESS, SALARY) " + "VALUES (?, ?, ?, ?, ?)"; try ...

    java+sql.rar_SQL java_java s_java sql_java sql 简单_java.sql.

    3. **Statement/PreparedStatement**:Statement用于执行静态SQL语句,而PreparedStatement允许预编译SQL语句,提高性能,并防止SQL注入攻击。 4. **ResultSet**:执行SQL查询后返回的结果集,可以通过遍历...

    数据库连接

    - SQL注入:字符串拼接形成的SQL语句容易受到SQL注入攻击,因为用户数据未经处理直接加入SQL语句。 - 性能:每次执行SQL语句时,数据库都需要解析并编译SQL,如果执行相同的SQL多次,这个过程会浪费资源。 相比之...

    Java SQL Server2008操作和sqljdbc4包

    `PreparedStatement`是更安全的选择,因为它可以防止SQL注入攻击。 在处理查询结果时,`ResultSet`对象是关键。它是一个从查询返回的结果集,可以迭代遍历每一行数据。例如: ```java try (Statement stmt = conn....

    计算机软件-商业源码-实例114-在程序中执行SQL语句.zip

    7. **安全性**:确保SQL语句的执行是安全的,避免SQL注入攻击。预编译的PreparedStatement是防范此类攻击的有效手段。 8. **错误处理和资源关闭**:在完成数据库操作后,记得关闭ResultSet、Statement和Connection...

    Java连接SQL源码

    `Statement`适用于静态SQL语句,而`PreparedStatement`适用于包含占位符的动态SQL,它可以提高性能并防止SQL注入攻击。 ```java try (Statement stmt = conn.createStatement()) { String sql = "CREATE TABLE ...

    java连接数据库 sql2000 sql2005 数据库的连接

    - 使用`PreparedStatement`而非`Statement`:`PreparedStatement`更安全,能防止SQL注入攻击,并且在执行预编译的SQL语句时效率更高。 - 使用连接池:在大型应用中,使用连接池(如C3P0、HikariCP等)管理数据库...

    JDBC.rar_Table_jdbc

    在实际开发中,为了提高性能和安全性,我们通常会采用PreparedStatement,并使用预编译的SQL语句,避免SQL注入攻击。此外,使用连接池(如C3P0、HikariCP等)可以有效管理数据库连接,减少连接创建和释放的开销。 ...

    JAVA与SQLServer数据库连接总结

    `Statement`适用于执行静态SQL,而`PreparedStatement`支持预编译的SQL,能有效防止SQL注入攻击。以下是一个使用`PreparedStatement`的例子: ```java String sql = "INSERT INTO users (name, email) VALUES (?, ?...

Global site tag (gtag.js) - Google Analytics