测试代码
import java.sql.*;
import org.junit.Test;
/**
* PreparedStatement与Statement对比、 PreparedStatement防止sql语句的注入原理与分析
* * @author baozq
* * 2018年3月14日
*/
public class SelectInject {
//模拟用户输入
static String name = "zhangsan\' or \'3\'=\'3";
static String password = "123";
@Test
public void testByStatement(){
try{
//调用Class.forName()方法加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
System.out.println("成功加载MySQL驱动!");
String url="jdbc:mysql://192.168.85.130:3306/test"; //JDBC的URL
Connection conn;
conn = DriverManager.getConnection(url, "root","root");
Statement stmt = conn.createStatement(); //创建Statement对象
System.out.println("成功连接到数据库!");
//注意带参的sql语句的书写
String sql = "SELECT * FROM user WHERE password='"+password+"' AND userName='"+name+"' ";
System.out.println(sql);
ResultSet rs = stmt.executeQuery(sql);//创建数据对象
System.out.println("编号"+"\t"+"姓名"+"\t"+"年龄");
while (rs.next()){
System.out.print(rs.getString(1) + "\t");
System.out.print(rs.getString(2) + "\t");
System.out.print(rs.getString(3) + "\t");
System.out.println();
}
rs.close();
stmt.close();
conn.close();
}catch(Exception e)
{
e.printStackTrace();
}
}
/**
* PreparedStatement可以有效地防止sql被注入
*/
@Test
public void testByPreparedStatement(){
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
//调用Class.forName()方法加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
System.out.println("成功加载MySQL驱动!");
String url="jdbc:mysql://192.168.85.130:3306/test"; //JDBC的URL
conn = DriverManager.getConnection(url, "root","root");
//获取连接
// conn = JdbcUtil.getConnection();
String sql = "SELECT * FROM user WHERE password=? AND userName=?";
//预编译
stmt = conn.prepareStatement(sql);
//设置参数
stmt.setString(1, password);
stmt.setString(2, name);
//执行sql
rs = stmt.executeQuery();
if(rs.next()){
//登录成功
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
System.out.println(sql);
System.out.println(stmt);
System.out.println(rs);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
try {
rs.close();
stmt.close();
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
打印SQL:
SELECT * FROM user WHERE password='123' AND userName='zhangsan' or '3'='3' ;
SELECT * FROM user WHERE password='123' AND userName='zhangsan\' or \'3\'=\'3';
执行结果:
更改测试数据:
static String name = "zhangsan' or '3'='3";
static String password = "123";
执行结果: 同上与上面一致;
总结:
Statement: 当输入‘ 或 \' 时 如果通过Statement调用SQL会转换为 ' 与字符串开始结束符号一样 而拼装为可执行SQL造成注入;
PreparedStatement:当输入‘ 或 \' 时 如果通过PreparedStatement调用SQL会转换为 \' 与字符串开始结束符号不一样 从而防止SQL注入;