PreparedStatement
作用: 预编译SQL的执行,,预防SQL注入问题
SQL注入
通过操作输入来修改预先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法;
SQL注入延时
需求,完成用户登录
select * from tb_user where username="zhangsan" and password = "123";
在JDBC API详解一种,可以将代码做如下修改即可完成SQL注入,即不需要知道密码也可以完成登录动作;
StringinputUser="zhangsan"; //登录成功 //StringinputPwd="123"; //登录失败 //StringinputPwd="123321"; //SQL注入 StringinputPwd="123'or'1'='1"; Stringsql="select*fromuserwhereusername='"+inputUser+"'andpassword='"+inputPwd+"'"; |
PreparedStatement
如何解决SQL注入,需要使用PreparedStatement
1, 获取PreparedStatement对象
Stringsql="select*fromuserwhereusername=?andpassword=?";
PreparedStatementpstmt=conn.prepareStatement(sql);
2, 设置参数值
PreparedStatement对象: setxxx(参数1,参数2),给?复制
pstmt.setString(1,inputUser);
pstmt.setString(2,inputPwd);
3, 执行SQL
pstmt.executeQuery();
packagelocal.content.jdbc;
importjava.sql.*;
//演示sql注入
publicclassjdbcDemo3{
publicstaticvoidmain(String[]args)throwsException{
//2.获取连接
Stringurl="jdbc:mysql://x.x.x.x:3306/test01?useSSL=false&serverTimezone=UTC";
Stringusername="test01_rw";
Stringpassword="12345";
Connectionconn=DriverManager.getConnection(url,username,password);
//3.定义sql
//用户输入的信息
StringinputUser="zhangsan";
//SQL注入
StringinputPwd="123'or'1'='1";
//防止SQL注入
String sql="select*fromuserwhereusername=?andpassword=?";
PreparedStatementpstmt=conn.prepareStatement(sql);
//设置?的值
pstmt.setString(1,inputUser);
pstmt.setString(2,inputPwd);
//执行sql
ResultSet rs=pstmt.executeQuery();
//6.根据结果判断是否登录成功
if(rs.next()){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
//7.释放资源
rs.close();
pstmt.close();
conn.close();
}
}
PreparedStatement原理
PreparedStatement好处
1,预编译SQL,性能更好
- 在获取PreparedStatement对象时,将sql语句发送给mysql进行检查,编译(这些步骤比较耗时)
- 执行时就不需要编译了,速度更快
- 如果sql模版一样,则只需要进行一次检查、编译即可
2,防止SQL注入:将敏感字符进行转义
预编译功能默认关闭,开启预编译功能: &useServerPrepStmts=true&cachePrepStmts=true
即:Stringurl="jdbc:mysql://x.x.x.x:3358/test01?useSSL=false&serverTimezone=UTC&useServerPrepStmts=true&cachePrepStmts=true";