JDBC学习笔记(6):PreparedStatement解决SQL注入问题

SQL注入问题:要求根据传入的name查询指定用户信息:

 1 package com.xxyh.jdbc;
 2 import java.sql.Connection;
 3 import java.sql.ResultSet;
 4 import java.sql.SQLException;
 5 import java.sql.Statement;
 6
 7 public class SQLInject {
 8
 9     public static void main(String[] args) throws SQLException {
10         read("‘or 1 or‘");
11     }
12
13     /**
14      * 根据用户名字查询用户信息
15      * @param name 用户姓名
16      * @throws SQLException
17      */
18     public static void read(String name) throws SQLException {
19         Connection conn = null;
20         Statement stmt = null;
21         ResultSet rs = null;
22         try {
23             conn = JdbcUtilsSingleton.getInstance().getConnection();
24             stmt = conn.createStatement();
25             String sql = "select id,name,birthday,money from user where name=‘"+name+"‘";
26             rs = stmt.executeQuery(sql);
27
28             while(rs.next()) {
29                 System.out.println(rs.getObject("id") + "\t" + rs.getObject("name") + "\t" +
30                         rs.getObject("birthday") + "\t" + rs.getObject("money"));
31             }
32         } finally {
33             JdbcUtilsSingleton.getInstance().close(rs, stmt, conn);
34         }
35     }
36 }

【运行结果】:

1    zhangs    1985-01-01    400.0

2    lisi    1986-01-01    200.0

3    wangwu    1987-01-01    300.0

结果是查询除了所有用户的信息 。原因是由于以上的SQL语句为:

select id,name,birthday,money from user where name=‘‘or 1 or‘‘

即查询name=‘’(空字符串)或者name=1的用户的信息,1表示布尔值真。因此整个语句相同于没有条件限制。

通过PreparedStatement反注入:

 1 public static void read2(String name) throws SQLException {
 2         Connection conn = null;
 3         PreparedStatement ps = null;
 4         ResultSet rs = null;
 5         try {
 6             conn = JdbcUtilsSingleton.getInstance().getConnection();
 7             String sql = "select id,name,birthday,money from user where name=?";
 8             // 在执行前进行预处理
 9             ps = conn.prepareStatement(sql);
10             ps.setString(1, name);// 1表示SQL语句里的第一个?
11             rs = ps.executeQuery();
12             while(rs.next()) {
13                 System.out.println(rs.getObject("id") + "\t" + rs.getObject("name") + "\t" +
14                         rs.getObject("birthday") + "\t" + rs.getObject("money"));
15             }
16         } finally {
17             JdbcUtilsSingleton.getInstance().close(rs, ps, conn);
18         }
19     }
  • 在SQL中包含特殊字符或SQL关键字(如:‘1 or 1’)时Statement将出现不可预料的结果(出现异常或查询结果不正确),可用PreparedStatement来解决。
  • PreparedStatement相对于Statement的优点:

>没有SQL注入的问题

>Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。

>数据库和驱动可以对PreparedStatement进行优化(只有对相关联的数据连接没有关闭的情况下有效)。

时间: 2024-12-31 13:14:41

JDBC学习笔记(6):PreparedStatement解决SQL注入问题的相关文章

PreparedStatement解决sql注入问题

总结 PreparedStatement解决sql注入问题 :sql中使用?做占位符 2.得到PreparedStatement对象 PreparedStatement pst=conn.prepareStatement(String sql); pst.setString(1,"aaa");//设置 第一个?的占位符赋值 pst.setString(2,"bbb"); // 查找用户 使用PreparedStatement 解决了 sql注入问题 public U

(MYSQL学习笔记5)防止SQL注入

MYSQL服务器并不存在共享池(我也不清楚共享池是什么)的概念,所以在MYSQL上使用绑定变量最大的好处就是为了防止SQL注入. PHP例子: $stmt = $dbh -> prepare("SELECT * FROM users WHERE username=? AND password=?"): $stmt -> execute(array($username,$password)); 即使传入的变量中,带有"angel ' or 1=1'"的条件

回头探索JDBC及PreparedStatement防SQL注入原理

概述 JDBC在我们学习J2EE的时候已经接触到了,但是仅是照搬步骤书写,其中的PreparedStatement防sql注入原理也是一知半解,然后就想回头查资料及敲测试代码探索一下.再有就是我们在项目中有一些配置项是有时候要变动的,比如数据库的数据源,为了在修改配置时不改动编译的代码,我们把要变动的属性提取到一个配置文件中,比如properties,因为properties里面都是键值对的形式,所以非常便于阅读和维护. 一.首先说说读取properties文件,这个相对路径和绝对路径的问题:

Java JDBC概要总结一(基本操作和SQL注入问题)

JDBC定义: JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API.JDBC是Java访问数据库的标准规范,可以为不同的关系型数据库提供统一访问,它由一组用Java语言编写的接口和类组成. JDBC规范(掌握四个核心对象): DriverManager类:用于注册驱动(管理控制驱动程序) Connection: 表示与数据库创建的连接 Statement: 操作数据库sql语句的对象 ResultSet: 结果集或一张虚

JDBC学习笔记四

PreparedStatement public interface PreparedStatement extends Statement;可以看到PreparedStatement是Statement的子接口,我们在执行查询或者更新数据表数据的时候,拼写SQL语句是一个很费力并且容易出错的事情,PreparedStatement可以简化这样的一个过程. PreParedStatement1).why?我们为什么要使用它 使用Statement需要进行拼写SQl语句,辛苦并且容易出错,之前使用

JDBC学习笔记(一)

public static void main(String[] args) { ResultSet rs = null; Statement stmt = null; Connection conn = null; try { /** * 1.加载JDBC驱动程序: * 加载目标数据库驱动到JVM * 成功加载后,会将Driver类的实例注册到DriverManager类 * oracle-Driver:oracle.jdbc.driver.OracleDriver * MySQL-Drive

dljd_013_使用PreparedStatement避免SQL注入攻击

一.使用PreparedStatement来避免SQL注入攻击示例 这里我只提供源码.测试类及结果截图信息.建库/表的语句详见上一集 package edu.aeon.logon; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import java.u

Oracle 学习笔记 17 -- 异常处理(PL/SQL)

程序在执行过程中出现异常是正常的,在程序的编写过程中出现异常也是不可避免的.但是要有相应的异常处理的机 制,来保证程序的正常执行.PL/SQL程序执行过程中出现的错误,称为异常.一个优秀的程序都应该能够正确处理 各种出错的情况,并尽可能的从错误中恢复.PL/SQL提供了异常处理机制. 概念: 异常处理(exception)是用来处理正常执行过程中未预料的事件,程序块的异常处理定义的错误和自定义的错误, 由于PL/SQL程序块一旦产生异常而没有指出如何处理时,程序就会异常的终止. 有三种类型的错误

IBatis.Net使用总结(一)-- IBatis解决SQL注入(#与$的区别)

IBatis解决SQL注入(#与$的区别) 在IBatis中,我们使用SqlMap进行Sql查询时,需要引用参数,在参数引用中可以使用两种占位符#和$.这两种占位符有什么区别呢? (1):#***#,进行预编译,采用参数化命令方式进行处理,有效防止sql注入,可以进行类型匹配.在模糊查询的时候,使用## (2):$***$, 不进行数据类型匹配,它只是简单的字符拼接.一般使用于非变量参数,例:select * from $tableName$ 对于不同的表执行统一的查询 1.2中*** 代表属性