大家好,又见面了,我是你们的朋友全栈君。
JDBC预处理对象prepareStatement概述
一、SQL注入问题
SQL注入:用户输入的内容作为了SQL语句语法的一部分,改变了原有SQL真正的意义。
假设有登录案例SQL语句如下:
SELECT * FROM 用户表 WHERE NAME = 用户输入的用户名 AND PASSWORD = 用户输的密码;
此时,当用户输入正确的账号与密码后,查询到了信息则让用户登录。但是当用户输入的账号为XXX 密码为:XXX’ OR ‘a’=’a时,则真正执行的代码变为:
SELECT * FROM 用户表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’ OR ’a’=’a’;
此时,上述查询语句时永远可以查询出结果的。那么用户就直接登录成功了,显然我们不希望看到这样的结果,这便是SQL注入问题。
为此,我们使用PreparedStatement来解决对应的问题。
二、代码演示SQL注入问题
(1)数据库准备
代码如下:
#创建sql_into数据库
CREATE DATABASE sql_into;
#使用sql_into数据库
USE sql_into;
#创建sql_into用户表
CREATE TABLE users(
uid INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(200),
PASSWORD VARCHAR(200)
);
#加入用户信息
INSERT INTO users(username,PASSWORD) VALUES('xiaoming','123'),('xiaoliang','456');
#查询用户信息
SELECT *FROM users;
mysql代码演示
(2)创建用户登录界面
public class StatementMyCode {
public static void main(String[] args) throws SQLException {
Scanner sc=new Scanner(System.in);
System.out.println("请输入用户名:");
String username =sc.nextLine();
System.out.println("请输入密码:");
String password=sc.nextLine();
//获取JDBCUtils连接
Connection con=JDBCUtils1.getConnection();
//Connection con= JDBCUtils1.getConnection();
//获取Statedment对象
Statement stat=con.createStatement();
//执行SQL语句
String sql = "select * from users where username='"+username+"' and password ='"+password+"'";
System.out.println(sql);
ResultSet rs=stat.executeQuery(sql);
if(rs.next()){
System.out.println("登录成功!");
}else{
System.out.println("登录失败!");
}
JDBCUtils1.close(rs,stat,con);
}
}
SQL注入出现的登录BUG
(3)配置文件代码
配置文件代码文件名需要和JDBCUtils1里的工具类的配置文件保持一致,配置文件代码文件名为config.properties
className=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/sql_into
user=root
password=root
(4)JDBCUtils1文件代码
public class JDBCUtils1 {
private static String url;
private static String user;
private static String password;
private static String className;
private JDBCUtils1(){}
static {
try{
Properties p=new Properties();
InputStream in = JDBCUtils1.class.getClassLoader().getResourceAsStream("config.properties");
p.load(in);
in.close();
url=p.getProperty("url");
user=p.getProperty("user");
password=p.getProperty("password");
className=p.getProperty("className");
//注册驱动
Class.forName(className);
}catch (Exception e){
e.printStackTrace();
}
}
public static Connection getConnection(){
//获取连接
Connection con=null;
try {
con= DriverManager.getConnection(url,user,password);
return con;
} catch (SQLException e) {
throw new RuntimeException("连接失败");
}
}
public static void close(ResultSet rs, Statement stat,Connection con){
try {
if(rs!=null)
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(stat!=null)
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (con!=null)
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
三、防止SQL注入 使用预处理对象
(1)原理介绍
preparedStatement:预编译对象,是Statement对象的子类。
特点:
- 性能高
- 会把sql语句先编译
- 能过滤掉用户输入的关键字。
PreparedStatement预处理对象,处理的每条sql语句中所有的实际参数,都必须使用占位符?替换。
String sql = "select * from user where username = ? and password = ?";
PreparedStatement使用,需要通过以下3步骤完成:
- PreparedStatement预处理对象代码:
// 获得预处理对象,需要提供已经使用占位符处理后的SQL语句
PreparedStatement psmt = conn.prepareStatement(sql) - 设置实际参数
void setXxx(int index, Xxx xx) 将指定参数设置指定类型的值
参数1:index 实际参数序列号,从1开始。
参数2:xxx 实际参数值,xxx表示具体的类型。
例如:
setString(2, “1234”) 把SQL语句中第2个位置的占位符?替换成实际参数 “1234” - 执行SQL语句:
int executeUpdate(); –执行insert update delete语句.
ResultSet executeQuery(); –执行select语句.
boolean execute(); –执行select返回true 执行其他的语句返回false.
(2)使用preparedStatement
用户登录界面代码演示
public class prepareStatementMyCode {
public static void main(String[] args) throws SQLException {
Scanner sc=new Scanner(System.in);
System.out.println("请输入用户名:");
String username =sc.nextLine();
System.out.println("请输入密码:");
String password=sc.nextLine();
//获取JDBCUtils连接
Connection con=JDBCUtils1.getConnection();
//Connection con= JDBCUtils.getConnection();
//获取Statedment对象
Statement stat=con.createStatement();
//执行SQL语句
String sql = "select * from users where username=? and password =?";
PreparedStatement ps = con.prepareStatement(sql);
ps.setObject(1,username);
ps.setObject(2,password);
System.out.println(sql);
ResultSet rs=ps.executeQuery();
if(rs.next()){
System.out.println("登录成功!");
}else{
System.out.println("登录失败!");
}
JDBCUtils1.close(rs,stat,con);
}
}
正确执行代码演示结果
SQL注入代码演示
四、使用prepareStatement完成查询数据
代码如下:
public class prepareStatementCSDNSelect {
public static void main(String[] args) {
//获取连接对象
Connection con=null;
PreparedStatement ps= null;
ResultSet rs = null;
try {
con= JDBCUtils1.getConnection();
String sql="select * from users";
ps = con.prepareStatement(sql);
rs = ps.executeQuery();
while(rs.next()){
int uid=rs.getInt("uid");
String username=rs.getString("username");
String password=rs.getString("password");
System.out.println(uid+" "+username+" "+password);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
JDBCUtils1.close(rs,ps,con);
}
}
}
使用prepareStatement完成查询
五、使用prepareStatement和javabean类完成查询
(1)创建user1类
代码如下:
/*一个类具备私有成员变量 空参构造方法 get/set 方法 实现序列化接口 那么称这个类为javabean类*/
public class User1 {
private int uid;
private String username;
private String password;
public User1() {
}
public User1(int uid, String username, String password) {
this.uid = uid;
this.username = username;
this.password = password;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User1{" +
"uid=" + uid +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
(2)使用把每条记录封装到user1对象中 将多个user1对象放到list集合当中
/*查询所有记录 把每条记录封装到user1对象中 将多个user1对象放到list集合当中*/
public class prepareStatementCSDNSelectBean {
public static void main(String[] args) {
//获取连接对象
Connection con=null;
PreparedStatement ps= null;
ResultSet rs = null;
try {
con= JDBCUtils1.getConnection();
String sql="select * from users";
ps = con.prepareStatement(sql);
rs = ps.executeQuery();
//定义一个集合用来存储user对象
List<User1> list=new ArrayList<>();
while(rs.next()){
int uid=rs.getInt("uid");
String username=rs.getString("username");
String password=rs.getString("password");
User1 u=new User1(uid,username,password);
list.add(u);
// System.out.println(uid+" "+username+" "+password);
}
System.out.println(list);
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
JDBCUtils1.close(rs,ps,con);
}
}
}
查询结果演示
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/137857.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...