在開發PHP 網站時,用戶登錄功能幾乎是不可或缺的一部分。然而,如果不小心處理用戶輸入,很容易受到SQL 注入攻擊。 mysqli::stmt_init是mysqli擴展提供的一個方法,可以配合預處理語句有效防止SQL 注入。本文將通過一個具體的例子介紹如何使用它實現一個安全的登錄驗證機制。
SQL 注入是一種攻擊技術,攻擊者通過在輸入字段中註入惡意SQL 語句,從而篡改原有的查詢邏輯。例如,如果直接拼接SQL:
$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
攻擊者可以輸入' OR '1'='1作為用戶名或密碼,使得查詢永遠為真,繞過認證。
mysqli::stmt_init用於初始化一個mysqli_stmt對象,它是實現預處理語句的第一步,能夠將SQL 與用戶輸入嚴格區分,從而有效防止注入攻擊。
以下是一個安全登錄表單驗證示例:
<?php
// 數據庫連接
$mysqli = new mysqli("localhost", "db_user", "db_password", "my_database");
// 檢查連接
if ($mysqli->connect_errno) {
die("連接失敗: " . $mysqli->connect_error);
}
// 用戶提交的用戶名和密碼
$username = $_POST['username'];
$password = $_POST['password'];
// 初始化一個預處理語句對象
$stmt = $mysqli->stmt_init();
// 編寫 SQL 查詢語句,使用 ? 佔位符
$sql = "SELECT id, password_hash FROM users WHERE username = ?";
// 準備語句
if ($stmt->prepare($sql)) {
// 綁定參數(s 表示 string 類型)
$stmt->bind_param("s", $username);
// 執行語句
$stmt->execute();
// 獲取結果
$stmt->bind_result($user_id, $password_hash);
// 判斷是否有結果
if ($stmt->fetch()) {
// 驗證密碼(假設數據庫中存儲的是 password_hash() 的結果)
if (password_verify($password, $password_hash)) {
echo "登錄成功,歡迎用戶 ID:$user_id";
// 設置會話或跳轉,例如:
// header("Location: https://m66.net/dashboard.php");
} else {
echo "密碼錯誤";
}
} else {
echo "用戶名不存在";
}
// 關閉語句
$stmt->close();
} else {
echo "SQL 語句準備失敗: " . $mysqli->error;
}
// 關閉連接
$mysqli->close();
?>
通過mysqli::stmt_init配合預處理語句使用bind_param ,我們可以有效阻止SQL 注入攻擊。開發中應始終使用預處理語句處理用戶輸入,尤其是在涉及數據庫操作時。此外,還應配合使用如password_hash()和password_verify()的函數來加強密碼安全性。
如果你正在構建一個登錄系統或用戶認證模塊,請優先使用這種方式,它比傳統的字符串拼接方式安全得多。