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