在 PHP 開發中,除了常見的表單登錄,還可以利用 HTTP 協議內建的基本認證機制,透過 Header() 函數發送 WWW-Authenticate 標頭,瀏覽器便會彈出原生的登錄對話框。這種方式無需額外的 HTML 表單,適合簡單的後台保護或 API 權限驗證。本文將詳細介紹如何使用 PHP_AUTH_USER 與 PHP_AUTH_PW 獲取用戶輸入的帳號密碼,並搭配資料庫進行驗證的完整流程。
當 PHP 腳本發送以下兩個標頭時,瀏覽器會攔截請求並顯示登錄框:
header('WWW-Authenticate: Basic realm="USER LOGIN"');
header('HTTP/1.0 401 Unauthorized');
用戶輸入帳號密碼後,瀏覽器會在後續請求中自動帶上 Authorization 標頭。PHP 會將解析後的用戶名存放在 $_SERVER['PHP_AUTH_USER'],密碼存放在 $_SERVER['PHP_AUTH_PW'](舊版本也可用 $PHP_AUTH_USER、$PHP_AUTH_PW,但建議統一使用超全局變數)。
以下範例展示從發送認證標頭、獲取憑證、連接 MySQL 資料庫查詢,到驗證失敗時重新發送 401 標頭的完整邏輯:
<?php
// 若未提供認證資訊,發送 401 強制瀏覽器彈出登錄框
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="Admin Area"');
header('HTTP/1.0 401 Unauthorized');
exit('請輸入有效的用戶名和密碼。');
}
// 獲取用戶提交的帳號密碼
$user = $_SERVER['PHP_AUTH_USER'];
$pass = $_SERVER['PHP_AUTH_PW'];
// 連接資料庫(建議改用 PDO 或 MySQLi)
$mysqli = new mysqli('localhost', 'db_user', 'db_pass', 'db_name');
if ($mysqli->connect_errno) {
die('資料庫連接失敗:' . $mysqli->connect_error);
}
// 使用預處理語句防止 SQL 注入
$stmt = $mysqli->prepare('SELECT id, name FROM users WHERE username = ? AND password = ?');
$stmt->bind_param('ss', $user, $pass); // 實際應存儲哈希值,此處為示範
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows === 0) {
// 驗證失敗,再次發送 401
header('WWW-Authenticate: Basic realm="Admin Area"');
header('HTTP/1.0 401 Unauthorized');
exit('用戶名或密碼錯誤。');
}
// 驗證成功,取得用戶資料
$stmt->bind_result($id, $name);
$stmt->fetch();
echo "歡迎,{$name} (ID: {$id})!";
// 後續業務邏輯...
$stmt->close();
$mysqli->close();
?>
password_hash() 與 password_verify()。$_SERVER['PHP_AUTH_USER'] 可能為空,需在 Apache 配置 SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0 並手動解析 $_SERVER['HTTP_AUTHORIZATION']。HTTP 基礎認證雖然樸素,卻是快速為特定目錄或 API 加上保護的有效手段。掌握 Header()、PHP_AUTH_USER、PHP_AUTH_PW 的配合使用,並注意安全最佳實踐,能讓你在適當場景下輕鬆實現用戶驗證。