✅作者简介:热爱国学的Java后端开发者,修心和技术同步精进。

个人主页:乐趣国学的博客

个人信条:不迁怒,不贰过。小知识,大智慧。

当前专栏:JAVA开发者成长之路

✨特色专栏:国学周更-心性养成之路

本文内容:【JAVA高级】——吃透JDBC中的SQL注入问题和解决方案

更多内容点击

【JAVA高级】——一文学会JDBC操作数据库

本文目录

SQL注入

✨什么是SQL注入

✨SQL注入的效果的演示

SQL注入代码

SQL注入效果

✨如何避免SQL注入

PrepareStatement解决SQL注入

✨PreparedStatement的应用

参数标记

动态参数绑定

✨综合案例

✨PreparedStatement总结

必须使用Statement的情况

投票传送门(欢迎伙伴们投票)


SQL注入

✨什么是SQL注入

在用户输入的数据中有SQL关键字或语法,并且关键字或语法参与了SQL语句的编译。导致SQL语句编译后的条件为true,一直得到正确的结果。这种现象就是SQL注入

✨SQL注入的效果的演示

SQL注入代码

package cn.bdqn.demo03;​import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.Scanner;​public class Login {​    public static void main(String[] args) throws ClassNotFoundException, SQLException {                //创建Scanner类对象,从控制台获取用户名和密码数据        Scanner sc = new Scanner(System.in);        System.out.println("请输入用户名:");        String user = sc.nextLine();//使用nextLine()方法获取字符串        System.out.println("请输入密码:");        String pwd = sc.nextLine();//使用nextLine()方法获取字符串                //1、注册驱动        Class.forName("com.mysql.jdbc.Driver");        //2、获取连接对象        String url = "jdbc:mysql://127.0.0.1:3306/java221804";        String dbuser = "root";        String pssword = "123456";        Connection connection = DriverManager.getConnection(url, dbuser, pssword);        //3、获取发送SQL语句的对象        Statement statement =connection.createStatement();        //编写SQL语句        String sql = "SELECT * FROM user WHERE username='"+user+"' AND pssword = '"+pwd+"';";        //4、执行SQL语句        ResultSet resultSet=statement.executeQuery(sql);        if(resultSet.next()){            System.out.println("用户名和密码正确,登录成功");        }else{            System.out.println("用户名或密码不正确,登录失败");        }        //6、关闭资源        resultSet.close();        statement.close();        connection.close();        sc.close();    }}

SQL注入效果

输入错误的用户名和密码,提示登录失败:

输入错误的用户名和密码,提示登录成功:产生了SQL注入

上面案例代码中,当你的用户名为 abc’ or 1=1;# 密码为123,拼接到SQL语句中,变成如下效果:

SELECT * FROM user WHERE username='abc' or 1=1;#' AND pssword = '123';

此SQL语句or 后面1=1永远正确,#后面的成了注释,所以这条语句会将表中所有的数据查询出来,然后再做数据判断的时候,就会得到正确结果,从而说用户名和密码正确,登录成功。

✨如何避免SQL注入

使用PreparedStatement代替Statement可以有效防止SQL注入的发生。由于SQL注入产生的原因是在用户输入数据对SQL整合,整合后再发送到数据库进行编译产生的。

所以为了避免SQL注入,就需要SQL语句在用户输入数据前就进行编译,成为完整的SQL语句,编译完成后再进行数据填充。这个操作需要使用PrepareStatement实现。

PreparedStatement利用预编译的机制将sql语句的主干和参数分别传输给数据库服务器,从而使数据库分辨的出哪些是sql语句的主干哪些是参数,这样一来即使参数中带了sql的关键字,数据库服务器也仅仅将他当作参数值使用,关键字不会起作用,从而从原理上防止了sql注入的问题。

PrepareStatement解决SQL注入

PreparedStatement接口继承了Statement接口,执行SQL语句的方法与Statement执行SQL语句的方法相同。

✨PreparedStatement的应用

PreparedStatement的作用:

  • 预编译SQL语句,效率高

  • 安全,避免SQL注入

  • 可以动态的填充数据,执行多个同结构的SQL语句

参数标记

//预编译SQL语句,SQL中的所有参数由?符号占位,这被称为参数标记。在执行SQL语句之前,必须为每个参数提供值。

String sql = “select * from user where userName = ” />

投票传送门(欢迎伙伴们投票)