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注入的問題得到了解決。

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