JDBC-PreparedStatement

    在前面使用的Statement中,编写sql语句使用的是拼接的形式,这样不仅可读性差,还非常容易导致出错,最大的问题是安全问题。

sql注入

    在需要用户输入的地方,用户输入的是SQL语句的片段,最终用户输入的SQL片段与我们DAO中写的SQL语句合成一个完整的SQL语句!例如用户在登录时输入的用户名和密码都是为SQL语句的片段!

    我准备了一张user表,上面有username和password用来模拟用户表,接下来准备了代码模拟登录过程

public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        try {

            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/esa?useSSL=false", "root", "123456");
            System.out.println("数据库连接成功");
            System.out.println("请输入用户名:");
            String name = sc.nextLine();
            System.out.println("请输入密码:");
            String pwd = sc.nextLine();
            String sql = "select count(1) from user where username = '"+name+"' and password = '"+pwd+"' ";
            Statement statement = conn.createStatement();
            ResultSet rs = statement.executeQuery(sql);
            rs.next();
            int count = rs.getInt(1);
            if (count > 0){
                System.out.println("登录成功");
            }else {
                System.out.println("登录失败");
            }
            if (statement != null){
                statement.close();
            }
            if (conn != null){
                conn.close();
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

通常情况下登录正常。 

但是!

 由于我们是拼接的sql语句,导致可以拼接上or '1' = '1'的语句,这样无论输入的账户密码是什么都会判断true,这种拼接的sql语句非常危险!

PreparedStatement

PreparedStatement是Statement的子接口,可以使用PreparedStatement来替换Statement。

PreparedStatement的好处:

  • 防止SQL攻击;

  • 提高代码的可读性,以可维护性;

  • 提高效率。

PreparedStatement的使用

  1. 使用Connection的prepareStatement(String sql):即创建它时就让它与一条SQL模板绑定;

  2. 调用PreparedStatement的setXXX()系列方法为问号设置值

  3. 调用executeUpdate()或executeQuery()方法,但要注意,调用没有参数的方法;

 此时sql语句用问号占位,写成:

String sql = "select count(1) from user where uswrname = ? and password = ?";

 还要传入参数填充占位,索引从1开始,如果不知道数据类型可以实现setObject:

stat.setString(1,name);
stat.setString(2,pwd);

 

   Scanner sc = new Scanner(System.in);
        try {

            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/esa?useSSL=false", "root", "123456");
            System.out.println("数据库连接成功");
            System.out.println("请输入用户名:");
            String name = sc.nextLine();
            System.out.println("请输入密码:");
            String pwd = sc.nextLine();

            String sql = "select count(1) from user where uswrname = ? and password = ?";
            PreparedStatement stat = conn.prepareStatement(sql);
            stat.setString(1,name);
            stat.setString(2,pwd);
            ResultSet rs = stat.executeQuery();
            rs.next();
            int count = rs.getInt(1);
            if (count > 0){
                System.out.println("登录成功");
            }else {
                System.out.println("登录失败");
            }
            if (stat != null){
                stat.close();
            }
            if (conn != null){
                conn.close();
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

这样就可以防止sql注入 

 

PreparedStatement最大的好处就是在于重复使用同一模板,给予其不同的参数来重复的使用它。这才是真正提高效率的原因。  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值