當前位置: 首頁> 最新文章列表> 用PDOStatement::fetchAll 查詢時,如何有效防止SQL 注入攻擊?

用PDOStatement::fetchAll 查詢時,如何有效防止SQL 注入攻擊?

M66 2025-06-28

什麼是SQL 注入?

SQL 注入是指攻擊者通過向SQL 查詢中插入惡意SQL 代碼,達到竊取、篡改數據,甚至控制數據庫服務器的目的。舉個例子,假如開發者直接將用戶輸入的內容拼接到SQL 查詢語句中,攻擊者可能通過輸入特定的SQL 代碼來改變查詢邏輯。

例如,假設有如下的查詢語句:

 $sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";

如果攻擊者輸入了以下內容作為用戶名或密碼:

  • 用戶名: ' OR '1'='1

  • 密碼: ' OR '1'='1

這個查詢語句就變成了:

 SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '' OR '1'='1';

這樣就繞過了正常的身份驗證,攻擊者可以輕鬆獲取到敏感數據。為了防止這種情況,我們可以使用參數化查詢(Prepared Statements)來保護應用程序免受SQL 注入攻擊。


使用PDO 防止SQL 注入

PDO 提供了一種防止SQL 注入的強大機制,即預處理語句( Prepared Statements )。通過預處理語句,查詢中的用戶輸入將被視為參數,而不是SQL 代碼的一部分,這樣即使用戶輸入惡意SQL 代碼,數據庫也不會執行它。

1. 使用PDO 連接數據庫

首先,你需要使用PDO 連接到數據庫。確保在創建連接時啟用異常處理,這樣可以更好地調試錯誤。

 try {
    $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'username', 'password');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    echo "數據庫連接失敗: " . $e->getMessage();
}

2. 使用預處理語句查詢

PDO 的預處理語句不僅能防止SQL 注入,還能提高查詢性能,尤其是在執行多次相同類型的查詢時。

假設我們有一個查詢需要根據用戶的username來檢索用戶數據。我們可以使用如下代碼:

 $sql = "SELECT * FROM users WHERE username = :username";
$stmt = $pdo->prepare($sql);

// 綁定參數
$stmt->bindParam(':username', $username, PDO::PARAM_STR);

// 執行查詢
$stmt->execute();

// 獲取查詢結果
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);

// 輸出結果
foreach ($results as $row) {
    echo "使用者名稱: " . $row['username'] . "<br>";
    echo "郵箱: " . $row['email'] . "<br>";
}

在上面的代碼中, :username是一個佔位符,用戶輸入的username會通過bindParam方法綁定到佔位符。這種方式會確保無論用戶輸入什麼內容,它都會作為一個參數傳遞給數據庫,而不是直接拼接到SQL 查詢中,從而有效防止SQL 注入。

3. 使用fetchAll 獲取結果

PDOStatement::fetchAll方法可以將查詢結果以數組的形式返回。它非常適合用於獲取多行數據。上面代碼中的fetchAll(PDO::FETCH_ASSOC)會將查詢結果按關聯數組的形式返回,其中每個元素對應一個數據行。

如果你想獲取所有的查詢結果,可以使用如下方式:

 $results = $stmt->fetchAll(PDO::FETCH_ASSOC);

如果你只需要單行結果,可以使用fetch方法,而如果你想獲取多行結果, fetchAll就是一個很好的選擇。

4. 使用URL 參數時的注意事項

在處理用戶輸入時,特別是URL 參數,應該始終使用預處理語句。比如當URL 中包含某個id參數,應該避免直接拼接到SQL 語句中,而是通過預處理語句來傳遞。

假設URL 中傳入了一個id參數,你可以使用如下代碼進行安全查詢:

 $id = $_GET['id'];  // 獲取 URL 中的 id 參數

$sql = "SELECT * FROM users WHERE id = :id";
$stmt = $pdo->prepare($sql);

// 綁定參數
$stmt->bindParam(':id', $id, PDO::PARAM_INT);

// 執行查詢
$stmt->execute();

// 獲取查詢結果
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
  • 相關標籤:

    SQL