SQL注入Statement与Preparement的区别
一般jdbc的执行流程
1.导包
2.加载驱动
通过反射拿到Driver对象:
Class.forName("driver")
3.建立连接
Connection connection=DriverManager.getConnection();
4.获取statment对象或预加载preparement
5.通过对象调用增删改查方法,返回整型的受影响行数或返回结果集后处理结果集
6.关闭连接
关闭连接时应注意先开的后关
例如:
写一个关闭流的方法
public static void close(Connection connection, Statement statement, ResultSet resultSet){ //先关后打开的 //关闭ResultSet集合 if(resultSet!=null){ try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } //关闭statement对象 if (statement!=null){ try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } //关闭connection连接 if (connection!=null){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } }
statement与预加载preparement的区别
不使用预加载:
Statement statement = connection.createStatement();//获取statement对象
在调用增删改executeUpdate()方法或查询executeQuery()方法时传入相应的SQL语句
例如:
public class Jdbc { public static void main(String[] args) throws ClassNotFoundException, SQLException { //1.驱动地址 String driver="com.mysql.jdbc.Driver"; //2.url数据库地址 String url="jdbc:mysql://localhost:3306/user?useSSL=false"; //3.数据库的账号 String username="root"; //4.数据库的密码 String password="123456"; //5.加载驱动 Class.forName(driver); //6.建立连接 Connection connection = DriverManager.getConnection(url, username, password); //获取statement对象 Statement statement = connection.createStatement(); }
SQL注入
由于程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候,没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患。用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据,这就是所谓的SQL Injection,即SQL注入。
在上面的一段代码中添加如下代码
Scanner scanner = new Scanner(System.in); System.out.println("请输入用户名:"); String user = scanner.nextLine(); System.out.println("请输入密码:"); String pass = scanner.nextLine(); //查询SQl语句 String sql=" SELECT * from student1 WHERE student1.student_name=\'"+user+"\' and student1.login_pwd=\'"+pass+"\'"; //调用查询executeQuery()方法 ResultSet resultSet = statement.executeQuery(sql); //判断resultSet集合中是否有下一个 while (resultSet.next()){ //输出数据库第一列的数据 System.out.println(resultSet.getObject(1)); System.out.println(resultSet.getObject(3)); System.out.println(resultSet.getObject(4));
数据库student1表:
输入正确的用户名密码
如果登录者在输入密码时恶意填入
1' OR '1'='1
就算用户名不对,他也拿到了数据库中所有的数据
应对这样的情况就要使用预加载
预加载preparement
1.获取prepareStatement
//?表示占位符 String sql = " select * from where username = ? and password = ? " //在创建的时候填写sql语句作为参数 PrepareStatement prepareStatement=connection.prepareStatement(sql)
2.设置占位符的值
//设置不同类型的参数,数字表示的是当前这个类型的第几个参数,推荐使用setObject prepareStatement.setString(1, username); prepareStatement.setString(2, password);
3.调用相应的增删改查方法,这时不需要再传入SQL语句,因为已经预加载了
ResultSet resultSet = prepareStatement.executeQuery();
将SQL语句预加载以后,我们在实验发现SQL注入没用了
总结:
当运行时动态地把参数传给PreprareStatement时, 即使参数里有敏感字符如 or’1=1’数据库也会把敏感字符作为一个参数,一个字段的属性值来处理而不会作为一个SQL指令, 如此,就起到了应对SQL注入的作用了!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)