回顾JDBC快速入门(四)中写的登录案例
会有一个sql注入的问题,如果我的用户名是随便输入的,密码这么输入a' or 'a' == 'a也会登陆成功:
通过打印出sql我们可以发现username = ‘abcdefg’ and password = 'a’是错误的,但是or 后边的‘a’ = 'a’是正确的,所以后边的逻辑就是永真,这样一来,就会查询所有的数据,然后自然会登录成功
用PreparedStatement解决问题
Statement所执行的sql是静态的sql,表示所有的sql语句,在执行之前,都是静态的,都是固定的拼接好的sql语句,不会再有变化,静态sql容易产生sql注入问题,而预编译的PreparedStatement则不会产生此类问题,他的参数都用?占位
其中在定义sql的时候就要这么定义select * from user where username = ? and password = ?,在执行sql对象的时候,用PreparedStatement来写pst = conn.prepareStatement(sql),这是预编译的过程,下面给sql赋值
如下pst.setString(1, username); pst.setString(2, password);我们把?的个数从1开始编号,然后分别按照1,2,3,4……的顺序去赋值,完成后就可以去执行他pst.executeQuery();里边不用传值,完整代码如下
package com.byzhang.jdbc; import com.byzhang.utils.JdbcUtils; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.PreparedStatement; import java.util.Scanner; public class JdbcDemo6 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入用户名:"); String username = sc.nextLine(); System.out.println("请输入密码:"); String password = sc.nextLine(); boolean flag = new JdbcDemo6().login(username, password); if(flag){ System.out.println("登录成功!"); }else{ System.out.println("登录失败!"); } } //登陆方法 public boolean login(String userName, String password) { if(userName == null || password == null){ return false; } Connection conn = null; PreparedStatement pst = null; ResultSet res = null; try{ conn = JdbcUtils.getConnection(); String sql = "select * from user where username = ? and password = ?"; System.out.println(sql); pst = conn.prepareStatement(sql); pst.setString(1, userName); pst.setString(2, password); pst.executeQuery(); return res.next(); }catch (SQLException e){ e.printStackTrace(); }finally { JdbcUtils.close(res, pst, conn); } return false; } }
以后的代码中,尽量用PreparedStatement。