一、使用 statement 存在的安全问题
(1)SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题
* 输入用户随便,输入密码:a' or 'a' = 'a
* select * from user where username = 'admin' and password = 'a' or 'a' = 'a';
之所以这样输入:a' or 'a' = 'a
是为了按照对应输入的sql语句,达到闭合的效果:
String sql = "select * from user where username = '" + username + "' " +
"and password = '"+ password + "'";
可以发现这里通过构造特殊的恒等式,能跳过密码验证实现登录。
二、使用 PreparedStatement 执行sql的对象
- 解决sql注入问题:使用
PreparedStatement
对象来解决 - 预编译的SQL:参数使用?作为占位符
- 步骤:
(1)导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
(2)注册驱动
(3)获取数据库连接对象 Connection
(4)定义sql
* 注意:sql的参数使用?作为占位符。 如:select * from user where username = ? and password = ?;
(5)获取执行sql语句的对象 PreparedStatement Connection.prepareStatement(String sql)
(6)给?赋值:
* 方法: setXxx(参数1,参数2)
* 参数1:?的位置编号 从1 开始
* 参数2:?的值
(7)执行sql,接受返回结果,不需要传递sql语句
(8)处理结果
(9)释放资源
- 注意:后期都会使用PreparedStatement来完成增删改查的所有操作
* 可以防止SQL注入
* 效率更高
三、代码实例
package jdbc;
import java.sql.*;
import java.util.Scanner;
public class JdbcDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名:");
String user = scanner.nextLine();
System.out.println("请输入密码:");
String password = scanner.nextLine();
boolean login = new JdbcDemo().login(user, password);
if (login) {
System.out.println("登录成功!");
}else {
System.out.println("用户名或密码错误!");
}
}
public boolean login(String username,String password){
if (username == null || password == null) {
return false;
}
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = JdbcUtils.getConnection();
String sql = "select * from user where username = ? and password = ?";
// 执行 sql 的对象 prepareStatement
preparedStatement = connection.prepareStatement(sql);
// 设置参数
preparedStatement.setString(1,username);
preparedStatement.setString(2,password);
// 执行sql
resultSet = preparedStatement.executeQuery();
return resultSet.next();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.close(resultSet,preparedStatement,connection);
}
return false;
}
}