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

PHP 表單密碼驗證與 HTTP 認證機制詳解

     編輯:PHP 相關知識

PHP 表單密碼驗證與 HTTP 認證機制詳解

PHP 提供了多種用戶認證方式,其中 HTTP 認證和表單驗證是最常見的兩種。本文深入解析這兩種認證機制的原理、實現方法及注意事項。

HTTP 認證機制

PHP 的 HTTP 認證僅在 Apache 模塊模式下有效(CGI 模式不支持)。通過 header() 發送 WWW-Authenticate 標頭,瀏覽器會彈出登錄對話框。用戶提交後,PHP 通過預定義變量獲取憑證:

  • $_SERVER['PHP_AUTH_USER'] - 用戶名
  • $_SERVER['PHP_AUTH_PW'] - 密碼
  • $_SERVER['AUTH_TYPE'] - 認證類型

支持 Basic 和 Digest(PHP 5.1.0+)兩種認證方式。

Basic HTTP 認證示例

<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="My Realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo '用戶取消登錄';
    exit;
} else {
    echo "<p>你好,{$_SERVER['PHP_AUTH_USER']}</p>";
    echo "<p>你的密碼是:{$_SERVER['PHP_AUTH_PW']}</p>";
}
?>

Digest HTTP 認證示例

Digest 認證更安全,密碼不會明文傳輸:

<?php
$realm = 'Restricted area';
$users = array('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('用戶取消登錄');
}

// 解析 PHP_AUTH_DIGEST
preg_match('/username="(?P<username>.*)",.*realm="(?P<realm>.*)",.*nonce="(?P<nonce>.*)",.*uri="(?P<uri>.*)",.*response="(?P<response>.*)",.*opaque="(?P<opaque>.*)",.*qop=(?P<qop>.*),.*nc=(?P<nc>.*),.*cnonce="(?P<cnonce>.*)"/', 
    $_SERVER['PHP_AUTH_DIGEST'], $digest);

if (!isset($users[$digest['username']])) die('無效用戶名!');

// 驗證響應
$A1 = md5($digest['username'] . ':' . $realm . ':' . $users[$digest['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'] . ':' . $digest['uri']);
$valid_response = md5($A1 . ':' . $digest['nonce'] . ':' . $digest['nc'] . ':' . $digest['cnonce'] . ':' . $digest['qop'] . ':' . $A2);

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

echo '登錄成功:' . $digest['username'];
?>

兼容性與安全注意事項

  • 標頭順序:IE 要求先發送 WWW-Authenticate 再發送 HTTP/1.0 401
  • 關鍵字大小寫:Basic 的 B 必須大寫,realm 值必須用雙引號
  • 安全模式:PHP 4.3.0+ 在安全模式下外部認證時不設置 PHP_AUTH 變量,可用 $_SERVER['REMOTE_USER']
  • 登出機制:發送 401 響應可清除瀏覽器緩存的認證信息(Lynx 除外)

強制重新認證示例

<?php
function authenticate() {
    header('WWW-Authenticate: Basic realm="Test Authentication System"');
    header('HTTP/1.0 401 Unauthorized');
    echo "請輸入有效的登錄信息\n";
    exit;
}

if (!isset($_SERVER['PHP_AUTH_USER']) ||
    ($_POST['SeenBefore'] == 1 && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
    authenticate();
} else {
    echo "<p>歡迎:{$_SERVER['PHP_AUTH_USER']}<br />";
    echo "舊認證:{$_REQUEST['OldAuth']}</p>";
    echo "<form action='{$_SERVER['PHP_SELF']}' METHOD='post'>";
    echo "<input type='hidden' name='SeenBefore' value='1' />";
    echo "<input type='hidden' name='OldAuth' value='{$_SERVER['PHP_AUTH_USER']}' />";
    echo "<input type='submit' value='重新認證' />";
    echo "</form>";
}
?>

表單密碼驗證(適用於 CGI 模式)

當無法使用 HTTP 認證時,可使用表單驗證:

<?php
if ($_POST['Submit'] == "提交") {
    $password = $_POST['password'];
    $cpassword = $_POST['cpassword'];
    
    if (empty($password) || empty($cpassword)) {
        die("密碼不可為空!");
    } elseif (strlen($password) < 5 || strlen($password) > 15) {
        die("密碼長度需在 5-15 位之間");
    } elseif (strlen($password) !== strlen($cpassword)) {
        die("兩次輸入長度不一致!");
    } elseif ($password !== $cpassword) {
        die("兩次密碼不匹配!");
    } else {
        // 密碼驗證通過,顯示掩碼
        for ($i = 0; $i < strlen($password); $i++) echo "*";
    }
}
?>
<html>
<head><title>表單驗證</title></head>
<body>
<form method="post" action="">
    請輸入密碼:<input type="password" name="password"><br>
    確認密碼:<input type="password" name="cpassword"><br>
    <input type="submit" name="Submit" value="提交">
</form>
</body>
</html>

基於數據庫的用戶驗證

實際項目中應結合數據庫驗證:

<?php
if (!isset($PHP_AUTH_USER)) {
    header('WWW-Authenticate: Basic realm="My Private Stuff"');
    header('HTTP/1.0 401 Unauthorized');
    echo '需要授權';
    exit;
} elseif (($PHP_AUTH_USER != "admin") || ($PHP_AUTH_PW != "123")) {
    header('WWW-Authenticate: Basic realm="My Private Stuff"');
    header('HTTP/1.0 401 Unauthorized');
    echo '授權失敗';
    exit;
} else {
    echo "<p>授權成功!</p>";
}
?>

建議生產環境使用加密存儲密碼(如 password_hash()),並採用 Prepared Statements 防止 SQL 注入。

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