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

PHP 處理 HTML 表單完全指南:從 `$_GET/$_POST` 到檔案上傳與安全防護

     編輯:PHP 綜合知識

表單提交基礎

<form action="handler.php" method="POST" enctype="multipart/form-data">
  <input type="text" name="username">
  <input type="password" name="pwd">
  <select name="role[]" multiple>
    <option value="admin">管理員</option>
    <option value="editor">編輯</option>
  </select>
  <input type="file" name="avatar">
  <button type="submit">送出</button>
</form>
  • method="GET":資料附加在 URL 查詢字串,長度受限 (~2KB),適合搜尋、分頁、可書籤操作。
  • method="POST":資料在 HTTP Body,無長度限制,適合寫入、上傳、敏感資訊。
  • enctype:`application/x-www-form-urlencoded` (預設) / `multipart/form-data` (檔案上傳必須)。

PHP 端接收變數

超全域陣列來源典型用途
`$_GET`URL 查詢字串搜尋關鍵字、分頁頁碼、篩選參數
`$_POST`POST Body (urlencoded)登入、註冊、設定儲存
`$_REQUEST`GET+POST+COOKIE (順序可配)**不建議直接使用**,來源模糊易導致安全漏洞
`$_FILES`multipart/form-data檔案上傳元資訊

多值欄位處理 (陣列語法)

<!-- HTML -->
<input type="checkbox" name="tags[]" value="php">
<input type="checkbox" name="tags[]" value="js">
<select name="roles[]" multiple>...</select>

<?php
// PHP 端
$tags = $_POST['tags'] ?? []; // ['php', 'js']
$roles = $_POST['roles'] ?? []; // ['admin', 'editor']

// 安全:確保為陣列
$tags = (array)($tags ?? []);
// 過濾空值
$tags = array_filter($tags, 'strlen');
?>

檔案上傳完整流程

<?php
// upload.php
$uploadDir = __DIR__ . '/uploads/';
$maxSize   = 2 * 1024 * 1024; // 2MB
$allowed   = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    exit('Method Not Allowed');
}

$file = $_FILES['avatar'] ?? null;
if (!$file || $file['error'] !== UPLOAD_ERR_OK) {
    $msg = $file['error'] ?? 'No file';
    exit("Upload error: $msg");
}

// 1. 檢查大小
if ($file['size'] > $maxSize) exit('File too large');

// 2. 檢查 MIME (不要信任瀏覽器提供的 type)
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime  = $finfo->file($file['tmp_name']);
if (!in_array($mime, $allowed, true)) exit('Invalid file type');

// 3. 安全檔名
$ext   = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
$name  = bin2hex(random_bytes(16)) . '.' . $ext;
$dest  = $uploadDir . $name;

// 4. 移動 (跨分區自動複製+刪除)
if (!move_uploaded_file($file['tmp_name'], $dest)) {
    exit('Move failed');
}

// 5. 設定權限 (僅擁有者可讀寫)
chmod($dest, 0600);

echo json_encode(['success' => true, 'path' => '/uploads/' . $name]);
?>

安全防護清單

  1. CSRF 保護:每個表單隱藏 ``,驗證 `hash_equals($_SESSION['csrf'], $_POST['csrf_token'])`。
  2. XSS 防禦:輸出時 `htmlspecialchars($str, ENT_QUOTES, 'UTF-8')`;儲存時**不**轉義,保留原始資料。
  3. SQL 注入:永遠使用 **Prepared Statements** (`$pdo->prepare()`),絕不拼接 SQL。
  4. 檔案上傳:驗證 MIME、副檔名、限制大小、儲存於非 Web 可執行目錄、重命名、掃描病毒 (ClamAV)。
  5. 輸入驗證:白名單驗證 (如 `in_array($role, ['admin','editor'])`),而非黑名單過濾。
  6. 速率限制:登入/註冊/發表單加入 CAPTCHA 或 Redis 計數器限流。

現代最佳實踐:PSR-7 + 中介層

// 使用 nyholm/psr7-server + laminas/laminas-httphandlerrunner
$request = ServerRequestFactory::fromGlobals();
$name = $request->getParsedBody()['username'] ?? '';
$files = $request->getUploadedFiles();
$avatar = $files['avatar'] ?? null;
if ($avatar && $avatar->getError() === UPLOAD_ERR_OK) {
    $avatar->moveTo($uploadDir . $newName);
}

優點:可測試、可遷移至 Swoole/RoadRunner、統一介面處理 CLI/HTTP 請求。

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