萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> PHP 程式設計

PHP $_GET、$_POST、$_REQUEST 超全域變數深度解析:差異、安全性與最佳實務

三大超全域變數對比

特性$_GET$_POST$_REQUEST
資料來源URL 查詢字串HTTP Request BodyGET + POST + COOKIE (順序由 variables_order 決定)
可見度URL 明文顯示Body 中,不顯示於 URL混合來源
長度限制~2000 字元 (瀏覽器/伺服器限制)受 post_max_size (預設 8M)取決於實際來源
編碼方式application/x-www-form-urlencodedapplication/x-www-form-urlencoded / multipart/form-data同上
適用場景搜尋、分頁、篩選、書籤分享、非敏感資料登入、註冊、上傳、修改/刪除、敏感資料不建議直接使用 (來源模糊)
安全性低 (歷史紀錄、Referer、日誌洩露)較高 (Body 不易外洩)最低 (Cookie 污染風險)
快取/書籤支援不支援視來源而定
瀏覽器後退正常提示重新提交視來源而定

實戰範例

GET 表單 (搜尋頁)

<form action="search.php" method="get">
  關鍵字: <input type="search" name="q" value="">
  分類: <select name="cat"><option value="">全部</option>...</select>
  <button type="submit">搜尋</button>
</form>

<?php // search.php
$q = $_GET['q'] ?? '';
$cat = $_GET['cat'] ?? '';
// 建構 SQL WHERE 子句...
?>

POST 表單 (會員登入)

<form action="login.php" method="post">
  <input type="hidden" name="csrf_token" value="">
  帳號: <input name="username" autocomplete="username" required>
  密碼: <input type="password" name="password" autocomplete="current-password" required>
  <button type="submit" name="action" value="login">登入</button>
</form>

<?php // login.php
if (($_POST['action'] ?? '') === 'login') {
    // 驗證 CSRF
    if (!hash_equals($_SESSION['csrf_token'] ?? '', $_POST['csrf_token'] ?? '')) {
        exit('非法請求');
    }
    $username = trim($_POST['username'] ?? '');
    $password = $_POST['password'] ?? '';
    // 驗證邏輯...
}
?>

$_REQUEST 的風險與棄用建議

<?php
// 危險範例:Cookie 覆蓋 POST 參數
// variables_order = "GPC" (預設)
// 攻擊者設定 Cookie: admin=1
// 正常用戶 POST: action=delete&id=5
// $_REQUEST['admin'] === '1' (來自 Cookie) -> 權限繞過風險

// 安全做法:明確指定來源
$action = $_POST['action'] ?? $_GET['action'] ?? null; // 明確優先順序
$admin  = $_SESSION['is_admin'] ?? false;             // 權限只信 Session
?>

進階:檔案上傳 ($_FILES)

<form action="upload.php" method="post" enctype="multipart/form-data">
  <input type="file" name="avatar" accept="image/*">
  <button>上傳</button>
</form>

<?php
$file = $_FILES['avatar'] ?? null;
if ($file && $file['error'] === UPLOAD_ERR_OK) {
    // 驗證 MIME (finfo)
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $mime = $finfo->file($file['tmp_name']);
    $allowed = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
    if (!in_array($mime, $allowed)) exit('檔案類型不允許');
    
    // 隨機檔名 + 移動
    $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
    $newName = bin2hex(random_bytes(16)) . '.' . $ext;
    $dest = __DIR__ . '/uploads/' . $newName;
    move_uploaded_file($file['tmp_name'], $dest);
    // 記錄資料庫...
}
?>

配置參數調優

; php.ini
post_max_size = 20M          ; POST 總體大小上限
upload_max_filesize = 10M    ; 單檔上限
max_file_uploads = 20        ; 同時上傳檔案數
max_input_vars = 3000        ; 最大輸入變數數量 (防 HashDoS)
max_input_time = 60          ; 解析輸入資料最長秒數
copyright © 萬盛學電腦網 all rights reserved