首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 表單驗證與 HTTP 認證完整指南:從 Basic 到 Digest

     編輯:PHP 綜合知識

兩大認證體系對比

特性表單驗證HTTP 認證
實現層級應用層(PHP 代碼控制)HTTP 協議層(瀏覽器原生對話框)
用戶體驗自定義登入頁、錯誤提示、記住我、驗證碼瀏覽器彈窗,樣式不可控,無法登出(需關閉瀏覽器)
安全性需自行防 CSRF、XSS、暴力破解Basic 傳輸 Base64(明文等效),必須配合 HTTPS;Digest 較安全
適用場景絕大多數 Web 應用內部 API、管理介面、WebDAV、RPC 端點
PHP 依賴無特殊要求僅 Apache 模組模式(mod_php)有效,CGI/FPM 不支援 PHP_AUTH_* 變數

HTTP Basic 認證實現

<?php
// 受保護頁面
if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="My Realm"');
    header('HTTP/1.0 401 Unauthorized');
    exit('取消登入');
}

// 驗證用戶名/密碼(實際查資料庫)
if ($_SERVER['PHP_AUTH_USER'] !== 'admin' || $_SERVER['PHP_AUTH_PW'] !== 'secret') {
    header('WWW-Authenticate: Basic realm="My Realm"');
    header('HTTP/1.0 401 Unauthorized');
    exit('帳號密碼錯誤');
}

echo "歡迎,{$_SERVER['PHP_AUTH_USER']}!";

HTTP Digest 認證實現(PHP 5.1+)

Digest 以挑戰-回應機制避免明文傳輸密碼,流程:

  1. 伺服器回傳 401 + WWW-Authenticate: Digest realm="...", nonce="...", qop="auth", opaque="..."
  2. 瀏覽器計算 response = MD5(MD5(user:realm:pass):nonce:nc:cnonce:qop:MD5(method:uri))
  3. PHP 解析 $_SERVER['PHP_AUTH_DIGEST'],同樣算法驗證 response。
<?php
$realm = 'Restricted area';
$users = ['admin' => 'mypass', 'guest' => 'guest'];

if (!isset($_SERVER['PHP_AUTH_DIGEST'])) {
    header('HTTP/1.1 401 Unauthorized');
    header('WWW-Authenticate: Digest realm="'.$realm.'", qop="auth", nonce="'.uniqid().'", opaque="'.md5($realm).'"');
    die('認證失敗');
}

// 解析 Digest 標頭
preg_match_all('@(\w+)=(?:(?:\"([^\"]+)\")|([^\s,]+))@', $_SERVER['PHP_AUTH_DIGEST'], $matches, PREG_SET_ORDER);
$digest = [];
foreach ($matches as $m) $digest[$m[1]] = $m[2] ?? $m[3];

if (!isset($users[$digest['username']])) die('用戶不存在');

// 計算合法 response
$A1 = md5("{$digest['username']}:$realm:{$users[$digest['username']]}");
$A2 = md5("{$_SERVER['REQUEST_METHOD']}:{$digest['uri']}");
$valid = md5("$A1:{$digest['nonce']}:{$digest['nc']}:{$digest['cnonce']}:{$digest['qop']}:$A2");

if ($digest['response'] !== $valid) die('憑證錯誤');

echo "登入成功:{$digest['username']}";

強制重新認證(登出)技巧

HTTP 認證無原生登出,常用手法:

  • 變更 realm 迫使瀏覽器重新彈窗。
  • 回傳 401 並提示用戶點擊「取消」後重新載入。
  • 前端配合 JS:fetch('/logout', {credentials: 'include'}) 但瀏覽器仍會快取憑證。
<?php
function authenticate() {
    header('WWW-Authenticate: Basic realm="Test System"');
    header('HTTP/1.0 401 Unauthorized');
    exit('請重新登入');
}

if (!isset($_SERVER['PHP_AUTH_USER']) || 
    (isset($_POST['SeenBefore']) && $_POST['OldAuth'] === $_SERVER['PHP_AUTH_USER'])) {
    authenticate();
}

echo "歡迎,{$_SERVER['PHP_AUTH_USER']}";
echo "<form method='post'><input type='hidden' name='SeenBefore' value='1'>
      <input type='hidden' name='OldAuth' value='{$_SERVER['PHP_AUTH_USER']}'>
      <button type='submit'>重新認證</button></form>";

表單驗證最佳實踐

  1. CSRF 保護:每個表單隱藏 <input name="csrf_token" value="">,驗證時比對。
  2. 密碼雜湊:password_hash($pwd, PASSWORD_DEFAULT) 存儲,password_verify($input, $hash) 驗證。
  3. 限流:同 IP/帳號 5 分鐘內失敗超 5 次鎖定 15 分鐘。
  4. HTTPS 強制:$_SERVER['HTTPS'] !== 'on' 時導向 HTTPS。
  5. 記住我:簽名 Cookie setcookie('remember', $token, time()+30*86400, '/', '', true, true),資料庫存 selector:hash(token)。

兼容性提醒

  • Apache + mod_php:$_SERVER['PHP_AUTH_USER'] 可用。
  • Nginx + PHP-FPM:不可用,需在 Nginx 做 auth_basic 或改用表單驗證。
  • CGI/FCGI 模式:PHP_AUTH_* 不會被填充。
  • 安全模式(已移除)下 PHP_AUTH_* 可能被阻擋,可用 $_SERVER['REMOTE_USER']。

總結

HTTP 認證適合簡單、內部、機器對機器場景;表單驗證是面向用戶 Web 應用的標準。現代專案強烈建議採用表單驗證 + HTTPS + 密碼雜湊 + CSRF 保護 + 限流,並在 API 端點使用 Bearer Token (JWT/OAuth2)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved