package com.bjpowernode.jdbc;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
/**
* 1.解决sql注入?
* 只要用户提供的信息不参与SQL语句的编译过程,问题就解决了。
* 要想用户信息不参与SQL语句的编译,那么必须使用java.sql.PreparedStatement
* PreparedStatement继承了java.sql.Statement
* 2.对比Statement和PreparedStatement
* -Statement存在sql注入问题,PreparedStatement解决了sql注入问题
* -Statement编译一次,执行一次。PreparedStatement编译一次,执行n次。PreparedStatement效率较高一些
* -PreparedStatement会在编译阶段做类型的安全检查
* PreparedStatement使用较多
*/
public class JDBCTest06 {
public static void main(String[] args) {
// 初始化界面
Map<String,String> userLoginInfo = initUI();
//验证用户名和密码
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; //这里使用PreparedStatement(预编译的数据库操作对象)
ResultSet res = null;
try {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","root");
//3.获取预编译的数据库操作对象
//以下是SQL语句的框子,其中一个?表示一个占位符,一个?将来接收一个"值",注意:占位符不能用单引号括起来。
String sql = "select * from t_user where loginName = ? and loginPwd = ?";
//程序执行到此处,会发送sql语句框子给DBMS,然后DBMS进行sql语句的预先编译
ps = conn.prepareStatement(sql);
//给占位符?传值(第1个问号下标是1,第2个问号下标是2,JDBC中下标从1开始)
ps.setString(1,loginName);
ps.setString(2,loginPwd);
//4.执行sql
// 以上正好完成了sql语句的拼接,以下代码的含义是:发送sql语句给DBMS,DBMS进行sql编译
//正好将用户提供的"非法信息"编译进去。导致了原sql语句的含义被扭曲了
//5.导致sql注入的根本原因是什么?
//用户输入的信息中含有sql语句的关键字,并且这些关键字参与了sql语句的编译过程,导致sql语句的原意被扭曲,进而达到sql注入
res = ps.executeQuery();
//5.处理结果集
if (res.next()){
loginSuccess = true;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//6.关闭资源
if (res != null){
try {
res.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return loginSuccess;
}
/**
* 初始化用户界面
* @return 用户输入的用户名和密码等登陆信息
*/
private static Map<String, String> initUI() {
Scanner s = new Scanner(System.in);
System.out.println("用户名: ");
String loginName = s.nextLine();
System.out.println("密码: ");
String loginPwd = s.nextLine();
Map<String,String> userLoginInfo = new HashMap<>();
userLoginInfo.put("loginName",loginName);
userLoginInfo.put("loginPwd",loginPwd);
return userLoginInfo;
}
}
JDBC__03__PreparedStatement用法
最新推荐文章于 2024-10-01 22:12:42 发布