防止注入攻击核心思想
通过预处理对象PreparedStatement,对SQL语句中参数列表进行指定传参,防止用户在SQL语句结尾上添加额外的SQL语句SQL语句中参数列表
每条SQL语句中的参数全部采用问号占位符
String sql = "insert into sort(sid,sname) values(?,?)"; PreparedStatement预处理对象代码: PreparedStatement psmt = conn.prepareStatement(sql);
实际参数传递
将指定参数设置为给定Java的xx值。在将此值发送到数据库时,驱动程序将它转换成一个 SQL Xxx类型值 void setXxx(int index, Xxx xx); 把SQL语句中第2个位置的占位符? 替换成实际参数 "mark" setString(2, "mark")
案例
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Scanner; public class JDBCAntiAttack { private static Scanner sc; public static void main(String[] args) { /* * 获取用户输入的用户名和密码 */ sc = new Scanner(System.in); System.out.println("请输入用户名:"); String name = sc.next(); System.out.println("请输入密码:"); String pass = sc.next(); /* * 连接数据库进行注入攻击 */ try { // 注册数据库 Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } String url = "jdbc:mysql://localhost:3306/mybase"; String username = "root"; String password = "root"; Connection conn = null; PreparedStatement pst = null; ResultSet rs = null; try { // 获取连接 conn = DriverManager.getConnection(url, username, password); //sql语句,执行验证查询 String sql = "SELECT * FROM USER WHERE uname=? AND upassword=?"; //预处理 pst = conn.prepareStatement(sql); pst.setObject(1, name); pst.setObject(2, pass); System.out.println(sql); //执行sql语句 rs = pst.executeQuery(); if(rs.next()){ System.out.println("用户名和密码验证通过!"); } else { System.out.println("用户名和密码验证不通过!"); } } catch (SQLException e) { e.printStackTrace(); }finally{ try { rs.close(); pst.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }