SQL注入及解决办法

SQL注入:(查询的百度解释如下)

  • 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击。

沿用上一篇博客中讲到的使用工具类来连接数据库
需求:请用户输入想要查询的姓名,并显示结果
这是users表的数据
在这里插入图片描述
代码如下:

import com.studycode.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;


public class Demo02 {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            //1.获取数据库连接
            connection = JDBCUtils.getConnection();
            //2.创建statement对象
            statement = connection.createStatement();
            //3.编写Sql语句
            System.out.print("请输入你要查询的用户名:");
            String username = scanner.nextLine();
            String sql = "select * from users where name = " +  username;
            System.out.println(sql);
            resultSet = statement.executeQuery(sql);
            while (resultSet.next()){
               System.out.println(resultSet.getString("name"));
                System.out.println(resultSet.getString("password"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //5.释放资源
            JDBCUtils.closeAll(resultSet,statement,connection);
        }
    }
}

代码看起来是没有问题的,思路也正确,但其实这样的代码是有问题的,以为在编写sql语句的时候采用了字符串拼接的形式,因此也就造成了漏洞…

  • 可以看到这是输入姓名为:java,因为users表中没有java这个名字,因此没有返回任何信息
    在这里插入图片描述
    根据之前学到的数据库基础知识,有与或非判断条件,因此可以采用此方式绕过检查以得到想要查询的信息,如下:
    在这里插入图片描述
    可以看到,当输入了’java’ or 1=1可以使用or语句的判断机制来绕过检查,这种方式称之为 SQL注入

可以采用prepareStatement类来代替Statement类解决sql注入问题

  • PreperedStatement是Statement的子类
  • 它的实例对象可以通过调用Connection.preparedStatement()方法获得,相对于Statement对象而言:PreperedStatement可以避免SQL注入的问题。

preparedStatement【推荐使用】 和 Statement的异同;

  • 相同点 : 都是用来执行sql语句的
  • 不同点 :
    1.Statement 不安全,会使数据库频繁编译SQL,不能预编译,不能使用占位符,容易造成SQL语句拼接错误
    2.preparedStatement 安全,预编译SQL语句,可以使用 ? 占位符,SQL更清晰。
    3.Statement 先写SQL语句再执行; Statement.execute(SQL)
    4.preparedStatement 直接编译SQL(使用?作为占位符),设置占位符的数据,调用方法执行 preparedStatement.execute();

可将上面代码优化如下:

import com.studycode.utils.JDBCUtils;
import java.sql.*;
import java.util.Scanner;

//防止SQL注入
public class Demo03 {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            //1.获取数据库连接
            connection = JDBCUtils.getConnection();
            System.out.print("请输入你要查询的用户名:");
            String username = scanner.nextLine();
            //2.创建preparedStatement对象
            preparedStatement = connection.prepareStatement("select * from users where name = ?");
            preparedStatement.setString(1,username);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()){
                System.out.println(resultSet.getString("name"));
                System.out.println(resultSet.getString("password"));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //5.释放资源
            JDBCUtils.closeAll(resultSet,preparedStatement,connection);
        }
    }
}

再次测试:
在这里插入图片描述
可以发现,SQL注入的问题得到了解决。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章