Statement和PreparedStatement的不同

1.使用Statement实现用户登录界面连接数据库,存在SQL注入现象

package denglianbin.jdbc;

import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
/*
* 存在的问题:
    请输入用户名:fdsa
    请输入密码:fdsa' or '1'='1
    登陆成功
   这种现象被称为SQL注入
   导致SQL注入的根本原因:用户输入的信息含有SQL语句的关键字,并且这些关键字参与了SQL语句的编译过程
                        导致原SQL语句的关键字被扭曲,进而达到SQL注入
*
* */
public class JDBCTest01 {
    public static void main(String[] args) {
        //初始化UI
        Map<String, String> userLoginInfo = initUI();
        //验证用户名和密码
        boolean loginSuccess = login(userLoginInfo);
        System.out.println(loginSuccess == true? "登陆成功" : "登陆失败");
    }

    private static boolean login(Map<String, String> userLoginInfo) {
        boolean loginSuccess = false;
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            //1.获取驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.获取连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/dlb_mysql",
                                         "root","123456");
            //3.获取数据库操作对象
            stmt = conn.createStatement();
            //4.执行SQL
            String sql = "select * from t_user where loginName = '" + userLoginInfo.get("loginName") + "' and loginPwd =" +
                         "'"+ userLoginInfo.get("loginPwd") + "'";
            //以上正好完成了SQL语句的拼接,以下代码的含义是发送SQL语句给DBMS,DBMS对SQL语句进行编译
            //正好将非法的用户信息编译进去,导致原SQL语句的含义被扭曲
            rs = stmt.executeQuery(sql);
            //5.处理结果集
            if(rs.next()){
                loginSuccess = true;
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            //6.释放资源
            if(rs != null){
                try {
                    rs.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if(stmt != null){
                try {
                    stmt.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if(conn != null){
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }

        return loginSuccess;
    }

    private static Map<String,String> initUI() {
        Scanner s = new Scanner(System.in);
        System.out.print("请输入用户名:");
        String loginName = s.nextLine();
        System.out.print("请输入密码:");
        String loginPwd = s.nextLine();
        Map<String, String> userLoginInfo = new HashMap<>();
        userLoginInfo.put("loginName", loginName);
        userLoginInfo.put("loginPwd", loginPwd);

        return userLoginInfo;
    }


}

2.PreparedStatement可以解决SQL注入的现象

package denglianbin.jdbc;

import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
/*
* 1.解决SQL语句的注入问题:
*       只要用户提供的信息不参与SQL语句的注入过程,问题就解决了
*       即使用户提供的信息中含有SQL语句的关键字,也不起作用。
*   要想使用户信息不参与SQL语句的编译,就必须使用java.sql.PreparedStatement
*   PreparedStatement接口继承了java.sql.statement
*   PreparedStatement是属于预编译的数据库操作对象。
*   PreparedStatement的原理是:预先对SQL语句的框架进行编译,再给SQL语句传值。
* 2.Statement和PreparedStatement的不同:*
*   -Statement存在SQL注入问题,PreparedStatement解决了SQL注入问题。
*   -Statement编译一次,执行一次;PreparedStatement编译一次,执行n次,PreparedStatement较高。
*   -PreparedStatement会在编译阶段做类型的安全检查。
*   故PreparedStatement使用的较多,只有极少数情况Statement草会用到。
*
*
*
*
* */
public class JDBCTest02 {
    public static void main(String[] args) {
        //初始化UI
        Map<String, String> userLoginInfo = initUI();
        //验证用户名和密码
        boolean loginSuccess = login(userLoginInfo);
        System.out.println(loginSuccess == true? "登陆成功" : "登陆失败");
    }

    private static boolean login(Map<String, String> userLoginInfo) {
        boolean loginSuccess = false;
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //1.获取驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.获取连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/dlb_mysql",
                    "root","123456");
            //3.获取预编译的数据库操作对象
            //这里的?代表占位符,其中一个?代表一个占位符,一个?接受一个“值”,注意占位符不能使用单引号括起来
            String sql = "select * from t_user where loginName = ? and loginPwd = ?";
            ps = conn.prepareStatement(sql);//程序执行到这里,会发送SQL语句框架给DBMS,然后DBMS对SQL语句进行预编译
            //给占位符传值,第一个下标为1,第二个下标为2,JDBC下表从1开始
            ps.setString(1, userLoginInfo.get("loginName"));
            ps.setString(2, userLoginInfo.get("loginPwd"));
            //4.执行SQL
            rs = ps.executeQuery();
            //gei
            //5.处理结果集
            if(rs.next()){
                loginSuccess = true;
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            //6.释放资源
            if(rs != null){
                try {
                    rs.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if(ps != null){
                try {
                    ps.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if(conn != null){
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }

        return loginSuccess;
    }

    private static Map<String,String> initUI() {
        Scanner s = new Scanner(System.in);
        System.out.print("请输入用户名:");
        String loginName = s.nextLine();
        System.out.print("请输入密码:");
        String loginPwd = s.nextLine();
        Map<String, String> userLoginInfo = new HashMap<>();
        userLoginInfo.put("loginName", loginName);
        userLoginInfo.put("loginPwd", loginPwd);

        return userLoginInfo;
    }
}

3.区别:

 -Statement存在SQL注入问题,PreparedStatement解决了SQL注入问题。
 -Statement编译一次,执行一次;PreparedStatement编译一次,执行n次,PreparedStatement较高。
 -PreparedStatement会在编译阶段做类型的安全检查。
 故PreparedStatement使用的较多,只有极少数情况Statement情况会用到。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值