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;
}
}