作用:
预编译sql语句执行:预防sql注入问题
sql注入:通过操作输入事先定义好的sql语句,用以达到执行代码达到对服务器进行攻击的方法
我输入的信息为账号是随便输入的:fdadf,
密码为 :' or'1'='1
也登录成功了
模拟一下sql注入
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
public class Test5 {
public static void main(String[] args) throws Exception{
//我现在数据表中只有一个 数据 t_username='zhangsan' t_password='123';
String url="jdbc:mysql:///TestUser";
String userName="root";
String PassWord="666";
Connection con=DriverManager.getConnection(url, userName, PassWord);//创建连接
Scanner sc=new Scanner(System.in);
System.out.println("请您输入账号:");
String username2=sc.nextLine();
System.out.println("请您输入密码:"); //模拟sql注入 输入 ' or'1'='1
String passwold2=sc.nextLine();
String sql="select * from tb_user where t_username='"+username2+"'and t_password=+ '"+passwold2+"' ";
Statement st=con.createStatement();
ResultSet rs=st.executeQuery(sql);
System.out.println(sql); //把他输出看看sql是啥
if(rs.next()) {//如果有数据肯定就是查到了
System.out.println("登录成功");
}else {
System.out.println("登录失败");
}
}
}
用Navicat打卡一下,主要是拼接出现了问题
select * from tb_user where t_username='fdadf'and t_password=+ ''or '1'='1'
解决sql注入
1获取PrepareStatement对象
Sql语句中的参数,使用?占位符代替
String sql="select * from user where username=? and password=?";
通过Connection 对象获取,并传入对象的sql语句
PreparedStatement ps=con.prepareStatement(sql);
2设置参数值
PrepareStatement对象:setXXX(参数1,参数2):给?赋值
Xxx:数据类型 ;如setInt(参数1,参数2)
参数:
参数1:? 的位置编号 ,从1开始
参数2: ?的值(变量)
3执行sql
executeUpdate()或者 executeQuery;不需要再传sql
没有问题的登录
package lib;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
public class Test7 {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub//我现在数据表中只有一个 数据 t_username='zhangsan' t_password='123';
String url="jdbc:mysql:///TestUser";
String userName="root";
String PassWord="666";
Connection con=DriverManager.getConnection(url, userName, PassWord);//创建连接
Scanner sc=new Scanner(System.in);
System.out.println("请您输入账号:");
String username2=sc.nextLine();
System.out.println("请您输入密码:");
String passwold2=sc.nextLine();
String sql="select * from tb_user where t_username=?and t_password=?";
PreparedStatement ps=con.prepareStatement(sql);//创建PrepareStatement对象
//设置参数
ps.setString(1, username2); //设置第一个问号
ps.setString(2, passwold2); //设置第二个个问号
ResultSet rs=ps.executeQuery(); //执行sql
if(rs.next()) {//如果有数据肯定就是查到了
System.out.println("登录成功");
}else {
System.out.println("登录失败");
}
}
}
PrepareStatement原理
好处:
预编译Sql,性能更高
防止sql注入,将敏感字符进行转义
1:PrepareStatement预编译功能开启:useServerPrepStmts=true ,在url中添加
String url="jdbc:mysql:///TestUser?useServerPrepStmts=true";
2配置Mysql执行日志(重启mysql服务器后生效) 配置到ini文件中
log-output=FILE
general-log=1
general_log_file="D:/mysql.log"
show-query-log=1
slow_query_log_file="D:\mysql_slow.log"
long_query_time=2
PrepareStatement原理:
1在获取PrepareStatement对象时,将sql语句发送给mysql服务器,进行检查,编译(这些步骤很耗时)
2执行时就不用再进行这些步骤了,速度更快
3如果sql模板一样,则只需进行一次检查,,编译