先看下面的代码
public class Demo { public static void main(String[] args) throws Exception { //1. 提示用户录入他/她的用户名或者密码, 并接收. Scanner sc = new Scanner(System.in); System.out.println("请录入您的账号: "); String username = sc.nextLine(); System.out.println("请录入您的密码: "); String password = sc.nextLine(); //2. 注册驱动. //3. 获取连接对象. Connection conn = JDBCUtils.getConnection(); //4. 根据连接对象, 获取可以执行SQL语句的对象. Statement stat = conn.createStatement(); //5. 执行SQL语句, 获取结果集. String sql = "select * from users where username='" + username + "' and password='" + password + "';"; ResultSet rs = stat.executeQuery(sql); //6. 操作结果集. System.out.println(rs.next() ? "登录成功" : "登录失败, 用户名或者密码错误!"); //7. 释放资源. JDBCUtils.release(conn, stat, rs); } }
这段代码中
//5.执行SQL语句,获取结果集 String sql = "select * from users where username='" + username + "' and password='" + password + "';";
当我们passoword输入一个 1 'or’1 时,系统会自动将用户输入的符号和sql语句中的符号相匹配,然后结果就变成了以下这样:
String sql = "select * from users where username=' " + username + " ' and password=' " + 1 'or' 1+ " ';";
这个条件始终成立,所以即使密码错误也能成功登录,因此我们需要使用预编译解决这个问题,不管用户传入什么内容,我们都当普通字符处理.
public class Demo { public static void main(String[] args) throws Exception { //1. 提示用户录入他/她的用户名或者密码, 并接收. Scanner sc = new Scanner(System.in); System.out.println("请录入您的账号: "); String username = sc.nextLine(); System.out.println("请录入您的密码: "); String password = sc.nextLine(); //2. 注册驱动. //3. 获取连接对象. Connection conn = JDBCUtils.getConnection(); //4. 根据连接对象, 获取可以执行SQL语句的对象. //在这一步, 已经确定好了SQL语句的格式, 之后不管传入什么内容, 都会只当做普通字符处理. String sql = "select * from users where username=? and password=?;"; PreparedStatement ps = conn.prepareStatement(sql); //给占位符填充值. ps.setString(1, username); //占位符的索引从1开始. ps.setString(2, password); //5. 执行SQL语句, 获取结果集. ResultSet rs = ps.executeQuery(); //因为SQL语句已经进行了预编译, 且被ps对象所记录, 所以在执行SQL语句时, 无需在传入SQL语句了. //6. 操作结果集. System.out.println(rs.next() ? "登录成功" : "登录失败, 用户名或者密码错误!"); //7. 释放资源. JDBCUtils.release(conn, ps, rs); } }