在PHP 開發中,防止SQL 注入攻擊是一項至關重要的安全實踐。使用預處理語句(prepared statements)和綁定參數(bind parameters)是目前最推薦的方式之一。其中, mysqli_stmt::attr_get函數雖然在使用上不如綁定參數直接,但在了解其作用和原理的過程中,對提高開發者的安全意識和技能也有積極意義。本文將介紹mysqli_stmt::attr_get的作用,並講解它在防止SQL 注入中的輔助作用。
mysqli_stmt::attr_get是一個用於獲取當前語句對象的屬性值的函數。其主要用途是在使用mysqli_stmt對象時,檢查或獲取一些內部屬性的值,以便進行進一步處理或調試。
語法如下:
public mysqli_stmt::attr_get(int $attribute): int|false
其中$attribute是你想獲取的屬性,例如MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH ,而返回值是該屬性的當前值,或者在失敗時返回false 。
雖然mysqli_stmt::attr_get本身並不直接防止SQL 注入,它更像是一個調試工具,但在使用預處理語句的過程中,它可以幫助開發者驗證語句執行的安全狀態,或用於確認參數綁定是否按預期生效。更重要的是,它讓開發者逐漸習慣通過mysqli_stmt對象進行操作,遠離直接拼接SQL 的高風險寫法。
下面我們通過一個使用預處理語句的例子來說明如何通過正規方法防止SQL 注入,並演示如何使用attr_get進行屬性檢查。
假設我們有一個用戶登錄系統,前端提交用戶名,我們需要根據該用戶名查詢數據庫中的記錄。
$username = $_GET['username'];
$sql = "SELECT * FROM users WHERE username = '$username'";
$result = $mysqli->query($sql);
如果用戶輸入的username是admin' -- ,上述SQL 將被拼接為:
SELECT * FROM users WHERE username = 'admin' --'
這就跳過了密碼驗證,造成嚴重安全漏洞。
$mysqli = new mysqli("localhost", "user", "password", "database");
$stmt = $mysqli->prepare("SELECT * FROM users WHERE username = ?");
$stmt->bind_param("s", $_GET['username']);
$stmt->execute();
$result = $stmt->get_result();
// 可選:檢查某個屬性值
$attr = $stmt->attr_get(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH);
if ($attr !== false) {
// 輸出屬性值,用於調試或驗證語句行為
echo "當前語句屬性:$attr";
}
在上述代碼中:
prepare()創建了一個預編譯的SQL 模板。
bind_param()將用戶輸入作為參數綁定,不會被當作SQL 代碼解析。
attr_get()可用於獲取語句屬性,在某些場景中可幫助開發者判斷語句對象當前的行為狀態。
假設我們要從一個提交表單的頁面https://m66.net/login.php獲取用戶名參數,查詢用戶信息:
<form action="https://m66.net/login.php" method="get">
<input type="text" name="username" />
<input type="submit" value="登入" />
</form>
服務端處理代碼:
$mysqli = new mysqli("localhost", "user", "password", "database");
$stmt = $mysqli->prepare("SELECT id, email FROM users WHERE username = ?");
$stmt->bind_param("s", $_GET['username']);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo "用戶ID:" . $row['id'] . "<br>";
echo "郵箱:" . $row['email'] . "<br>";
}
// 使用 attr_get 檢查屬性
$attr = $stmt->attr_get(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH);
if ($attr !== false) {
error_log("stmt 屬性:$attr", 0);
}
雖然mysqli_stmt::attr_get並非直接用於防止SQL 注入的函數,但在使用mysqli_stmt接口進行參數化查詢的上下文中,它是了解語句對象狀態的有力工具。結合prepare()和bind_param()使用,它不僅幫助構建安全的查詢,還能增強代碼的可調試性和健壯性。開發者應始終優先使用參數化查詢,並利用諸如attr_get之類的工具函數進一步加強代碼的透明度與安全控制。