package com.bjpowernode.jdbc; import java.sql.*; import java.util.HashMap; import java.util.Map; import java.util.Scanner; /** * @Author:杨青 * @Time:2021/10/26 10:54 * @Description: * 1.解决SQL注入问题 * 只要用户提供的信息不参与SQL语句的编译过程,问题就解决了。 * 即使用户提供的信息中含有SQL语句的关键字,但是没有参与编译,不起作用 * 要想用户信息不参与SQL语句的编译,就必须使用java.sql.PreparedStatement * PreparedStatement是属于预编译的数据库操作对象 * PreparedStatement的原理是:预先对SQL语句的框架进行编译,然后再给SQL语句传‘值’ * 2.测试结果: * 用户名:fdsa * 密码:fdsa' or '1'='1 * 登陆失败 * 3.解决SQL注入的关键是: * 用户提供的信息中即使含有sql语句的关键字,但是这些关键字并没有参与编译,不起作用 * 4.对比Statement和PreparedStatement * -Statement存在sql注入问题,PreparedStatement解决了sql注入问题 * -Statement是编译一次执行一次,Prepared Statement是编译一次,可执行N次,PreparedStatement效率较高一些 * -PreparedStatement会在编译阶段做类型的安全检查 * 综上所述: * PreparedStatement使用较多,只有极少数的情况下需要使用Statement * 5.什么情况下必须使用Statement? * 业务方面要求必须支持sql注入的时候 * Statement支持sql注入,凡是业务方面要求是需要进行sql语句拼接的,必须使用Statement */ public class JDBCTest07 { public static void main(String[] args) { //初始化一个界面 Map<String,String> userLoginInfo=userinitUI(); //验证用户名和密码 boolean loginSuccess=login(userLoginInfo); System.out.println(loginSuccess?"登陆成功!":"登陆失败!"); } /** * 用户登陆 * @param userLoginInfo 用户登陆信息 * @return false表示失败,true表示成功 */ private static boolean login(Map<String, String> userLoginInfo) { //打标记的意识 boolean loginSuccess=false; //单独定义变量 String loginName=userLoginInfo.get("loginName"); String loginPwd=userLoginInfo.get("loginPwd"); //JDBC代码 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/bjpowernode","root","123456"); //3.获取预编译的数据库操作对象 //sql语句的框架,一个?表示一个占位符,一个?将接收一个‘值’,注:占位符不能使用单引号括起来 String sql = "select *from t_user where loginName=? and loginPwd=?"; //程序执行到此处,会发送sql语句框架给DBMS,然后DBMS进行sql语句的预编译 ps=conn.prepareStatement(sql); //给占位符?传值(第一个问号下标是1,第二个问号下标是2,JDBC中所有下标从1开始) ps.setString(1,loginName); ps.setString(2,loginPwd); //4.执行sql语句 rs=ps.executeQuery(); //5.处理结果集 if(rs.next()){ //登陆成功 loginSuccess=true; } } catch (Exception e) { e.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; } /** * 初始化用户界面 * @return 用户输入的用户名和密码等登陆信息 */ private static Map<String, String> userinitUI() { Scanner scanner=new Scanner(System.in); System.out.print("用户名:"); String loginName=scanner.nextLine(); //得到用户名 System.out.print("密码:"); String loginPwd=scanner.nextLine(); //得到密码 Map<String ,String> userLoginInfo=new HashMap<>(); userLoginInfo.put("loginName",loginName); //将loginName组装到Map中 userLoginInfo.put("loginPwd",loginPwd); //将loginPwd组装到Map中 return userLoginInfo; } }