選修單元 B EBCH3:表單、GET/POST、伺服器端有效性檢驗、曲奇、Session

本章以 HTML 表單為起點,逐步連接至 PHP$_GET$_POST 接收資料。 你將學會依情境選用 GET 與 POST、在伺服器端進行有效性檢驗,並理解曲奇(Cookie)與 Session 的用途、限制與風險。 章末提供 20 題 Coding 以鞏固整體流程。

1HTML 表單:從零建立與常用輸入元件

學習重點

  • <form> 用於收集輸入:action 指定提交目標,method 指定 GET 或 POST。
  • name 代表「提交欄位名稱」:PHP 以 $_GET["name"]$_POST["name"] 取值。
  • id 主要供 CSS/JavaScript 選取、以及 <label for> 對應;不等同提交欄位。
  • 常用輸入元件:textpassworddatetime(時間選擇器)、select複選框(checkbox)、submit

表單骨架:最少需要哪些欄位?

<form action="handle.php" method="post"> <label>姓名:<input type="text" name="studentName"></label> <button type="submit">提交</button> </form>
  • 提交目標action 指向負責處理的 PHP 檔案。
  • 提交方法method 決定用 $_GET 還是 $_POST 接收。
  • 欄位命名:每個需要提交的元件必須具備 name

常用輸入元件與適用情境

元件HTML 範例常見用途注意事項
文字框 <input type="text" ...> 姓名、關鍵字、一般文字 仍需伺服器端有效性檢驗(例如長度)
密碼框 <input type="password" ...> 密碼輸入 只遮蔽顯示,不代表安全;不可把明文密碼存入曲奇
日期 <input type="date" ...> 生日、日期選擇 不同瀏覽器呈現略異;伺服器端仍要檢查格式
時間 <input type="time" ...> 預約時間、上課開始時間 伺服器端仍要檢查格式與合理範圍(例如只接受 08:00–18:00)
下拉式選單 <select name="...">...</select> 班別、選項限制輸入範圍 伺服器端應用 in_array() 驗證值是否在允許清單
複選框 <input type="checkbox" ...> 興趣多選 多值建議用 name="x[]",伺服器端以陣列接收
提交按鈕 <button type="submit">...</button> 提交表單 可配合必填提示,但不可取代伺服器端檢查

代碼小練習:表單實作(2 個任務)

每個任務均提供:提示/核對答案/顯示參考答案。請在下方以分頁切換任務,逐題完成。

任務 1:重組示範表單(填寫 action/method/class)

  • 只修改標示為 TODO 的位置:actionmethod、以及每個 labelclass
  • 完成後按「核對答案」:系統會檢查表單是否使用指定的提交位置及排版類別。

2GET 與 POST 的選用原則

學習重點

  • GET:資料出現在劃一資源定位(URL)的查詢字串;適合搜尋、篩選、分享結果。
  • POST:資料放在 request body;較適合登入、提交個人資料、更新操作。
  • PHP 接收:GET 用 $_GET;POST 用 $_POST;顯示回頁面時應使用 htmlspecialchars()

差異、優缺點與適用情境(表格)

比較項GETPOST
資料位置URL 查詢字串(可見)request body(URL 不直接顯示)
可分享/可書籤容易(URL 包含參數)一般不便(URL 不含提交內容)
私隱與保安較弱:容易被記錄於瀏覽器歷史、伺服器日誌較佳:不直接暴露於 URL(但仍需 HTTPS 才能保護傳輸)
資料量受 URL 長度限制一般可提交較多資料
常見用途搜尋、排序、篩選、分頁登入、註冊、提交表單、更新/刪除操作

選用原則:以問題導向作判斷

  1. 需要分享或收藏結果嗎?若需要,通常選 GET(例如搜尋結果)。
  2. 包含敏感資料嗎?若包含(例如密碼、身份資料),應選 POST,並配合 HTTPS。
  3. 資料是否會改變伺服器狀態?若會(新增/更新/刪除),一般選 POST(或其他方法)。
  4. 資料量是否較大?若較大,通常選 POST。

即時示範:GET 搜尋(顯示輸入)

Checkpoint:GET 與 POST 的選用原則(≥40 題)

本小測以四選一為主,涵蓋情境判斷、URL 可見性、長度限制與私隱風險。

3伺服器端有效性檢驗:不可只依賴客戶端

學習重點

  • 客戶端(client-side)檢查可提升體驗,但可被關閉或繞過;最終必須由伺服器端(server-side)把關。
  • 常用函數:isset()empty()in_array()is_numeric()is_string()strlen()strpos()
  • 典型流程:存在性 → 必填 → 型別/格式 → 範圍/白名單 →(需要時)輸出前處理。

常用函數速查:檢查甚麼、回傳甚麼、常見陷阱

函數檢查內容回傳值(重點)常見陷阱/注意簡例
isset($x) 變數是否存在且不為 null 布爾值:存在且非 nulltrue 只代表「存在」,不代表「不空」 if(isset($_POST['name'])) ...
empty($x) 是否為「空值」 布爾值:空 → true "0" 亦視為空;若 0 合法,應改用更精準判斷 if(empty($_POST['age'])) ...
in_array($v,$arr) 值是否在允許清單(白名單)內 布爾值:找到 → true 必要時使用第三參數 true 作嚴格比較 in_array($cls,$allow,true)
is_numeric($x) 是否可視為數值 布爾值 通過後仍建議轉型(例如 (int))再作範圍檢查 if(!is_numeric($age)) ...
is_string($x) 是否為字串(string) 布爾值 表單輸入多數是字串;更常用的是長度/格式/白名單 if(is_string($name)) ...
strlen($s) 字串長度 整數 用於最少/最多字元限制;輸入前可先 trim() if(strlen($pw)<8) ...
strpos($s,$sub) 子字串首次出現的位置 整數位置或 false 0 代表「在第一個位置找到」;判斷找不到必須用 === false if(strpos($email,'@')===false) ...

代碼小練習:以多個函數完成輸入檢查(填空題|7 個任務)

請以分頁切換任務。每個任務均提供:提示/核對答案/顯示參考答案/講解;請只修改題目標示為 TODO 的位置。

任務 1:用 isset() 檢查欄位是否存在

  • 在伺服器端先確認必須欄位(例如 userage)是否存在於 $_POST
  • 如缺少欄位,請把訊息加入 $errors,並輸出錯誤清單。

Checkpoint:伺服器端有效性檢驗(≥40 題)

本小測以四選一為主,包含:函數配對、常見陷阱(特別是 strpos())、以及程式片段判讀。

4曲奇(Cookie):用途、好處與壞處、適用與不適用情境

學習重點

  • 曲奇是瀏覽器儲存的小型文字檔案,並會在之後的請求自動帶回伺服器。
  • 常見用途:記住偏好(主題、語言)、保留某些狀態(例如「已同意提示」)。
  • 風險:曲奇可被竄改,亦可能被用於追蹤;不應存放敏感資料(例如明文密碼)。

曲奇可存甚麼?不應存甚麼?

  • 適合:偏好設定(例如字體大小、介面主題)、非敏感標記(例如「已完成新手導覽」)。
  • 不適合:明文密碼、身份證號碼等敏感資料;以及會直接影響權限的關鍵資料(除非配合簽署/伺服器端驗證)。

基本用法:設置與讀取

<?php // 設置:把鍵值寫入曲奇(實務上可加入有效期等參數) setcookie("username", "amy", time() + 86400); // 讀取:從 $_COOKIE 取得 $u = $_COOKIE["username"] ?? ""; echo "歡迎," . htmlspecialchars($u); ?>

即使資料來自曲奇,仍應視為外來輸入:必要時要做伺服器端驗證,輸出前亦要使用 htmlspecialchars()

清除指定曲奇:把有效期設為過去

<?php // 刪除:把同名曲奇的有效期設為過去(並確保 path 與建立時一致) setcookie("username", "", time() - 3600, "/"); ?>

要成功刪除曲奇,path/domain 等參數必須與原本設置時一致;否則可能出現「看似刪除,但實際上仍存在」的情況。

互動示範:以曲奇(Cookie)記住使用者名稱(可試玩)

情境:網站希望在使用者下次回訪時顯示「歡迎回來,使用者名稱」。 請在下方模擬器輸入名稱並提交,然後再次提交或按「執行」,觀察 $_COOKIE 的變化;再按「清除曲奇」。

注意:此模擬器為教學用途,setcookie() 在同一次執行中亦會即時反映於 $_COOKIE(與真實伺服器環境「下次請求才會讀到」的行為略有差異)。

Checkpoint:曲奇(Cookie)(≥40 題)

本小測以四選一為主,涵蓋用途、好處/壞處、以及情境判斷(應否使用曲奇)。

5Session:概念、基本用法與曲奇的分別

學習重點

  • Session 用於在伺服器端保存用戶狀態(例如登入狀態),並可跨多次請求維持。
  • 基本流程:session_start() → 讀寫 $_SESSION[...] →(需要時)登出清除。
  • Session 與曲奇的關係:瀏覽器通常會保存一個 Session ID(常以曲奇形式帶回),伺服器端再以此對應 Session 資料。

甚麼是 Session?為何常用於登入?

HTTP 請求本質上無狀態;若要「記住」某位用戶已通過身份核對,便需要保存狀態。 Session 把狀態資料放在伺服器端,通常只把一個識別碼交由瀏覽器保存並帶回,因此比把完整狀態直接放在曲奇更合適用於登入。

基本流程(示意)

  1. 在需要使用 Session 的頁面最上方呼叫 session_start()
  2. 登入成功後:設定 $_SESSION["logged_in"] = true,並保存必要的用戶識別資料(例如 user_id)。
  3. 受保護頁面:先檢查 $_SESSION 是否存在登入標記;不符合則導向登入頁。
  4. 登出:清除 Session(例如 session_unset()session_destroy())。

代碼示範:登入、受保護頁面與登出

以下以三個檔案示範最基本流程:登入成功後建立 Session;受保護頁面先檢查 Session;登出時清除 Session。實務上仍需配合 HTTPS、伺服器端有效性檢驗及更嚴謹的權限控制。

login.php(建立 Session)

<?php session_start(); if (!empty($_POST)) { $user = trim($_POST['user'] ?? ''); $pw = trim($_POST['pw'] ?? ''); // 示範:以固定帳號/密碼判斷(實務應使用資料庫與雜湊) if ($user === 'student' && $pw === 'abc') { $_SESSION['logged_in'] = true; $_SESSION['username'] = $user; header('Location: welcome.php'); exit; } else { $error = '帳號或密碼錯誤。'; } } ?> <form method="post"> <label class="inline-input">帳號:<input name="user"></label> <label class="inline-input">密碼:<input type="password" name="pw"></label> <button class="btn" type="submit">登入</button> </form> <?php if (!empty($error)) echo '<p>' . htmlspecialchars($error) . '</p>'; ?>

welcome.php(檢查 Session)

<?php session_start(); if (empty($_SESSION['logged_in'])) { header('Location: login.php'); exit; } $u = $_SESSION['username'] ?? ''; ?> <p>歡迎,<strong><?php echo htmlspecialchars($u); ?></strong>!</p> <p><a href="logout.php">登出</a></p>

logout.php(清除 Session)

<?php session_start(); session_unset(); session_destroy(); header('Location: login.php'); exit; ?>

互動示範:以 Session 保存登入狀態(可試玩)

情境:網站需要在多次 HTTP 請求之間保存「已登入」狀態。 請在下方模擬器使用測試帳號登入,觀察登入後內容如何由 $_SESSION 控制;再按「登出」清除 Session。

此示範把「登入頁面」與「會員區」寫在同一檔案內,以便在模擬器中試玩;在真實網站中可拆成多頁並配合導向(redirect)流程。

Session 與曲奇:如何比較?

項目曲奇(Cookie)Session
主要儲存位置客戶端(瀏覽器)伺服器端
資料可否被用戶改動較容易(可被修改)較難(用戶通常只持有 Session ID)
常見用途偏好、非敏感狀態登入狀態、權限控制
保安重點不應存敏感資料;內容需驗證保護 Session ID、避免被盜用;伺服器端設計需嚴謹

Checkpoint:Session 概念與流程(≥40 題)

本小測以四選一為主,涵蓋 Session 基本概念、session_start()$_SESSION 用法,以及 Session vs 曲奇分辨。

6其他常見延伸課題:表單安全、XSS 與錯誤訊息

學習重點

  • 不要信任前端:客戶端限制可被繞過;伺服器端必須以白名單(允許清單)做檢查。
  • 基本輸入清理(輸出前處理):把用戶輸入顯示回頁面前,使用 htmlspecialchars() 降低 XSS 風險。
  • 錯誤訊息設計:避免洩露伺服器細節(檔案路徑、SQL、堆疊追蹤),同時提供足夠提示讓用戶修正。

表單安全:以白名單驗證為核心

前端可提供下拉式選單限制輸入,但用戶仍可自行構造請求提交未列於選單的值。 因此伺服器端應把可接受的值列入「允許清單」,並以 in_array() 等方法檢查;不符合即拒絕處理。

<?php $allow = ["1A","1B","1C"]; $cls = $_POST["class"] ?? ""; if (!in_array($cls, $allow, true)) { die("班別不在允許清單內。"); } ?>

XSS 基本概念:為何要做輸出前處理?

若把用戶輸入直接輸出到網頁,輸入內容可能被瀏覽器當作 HTML/JavaScript 解讀,造成跨網站腳本攻擊(XSS)。 基本防線是:在輸出前使用 htmlspecialchars() 把特殊字元轉換為安全形式。

<?php $msg = $_GET["msg"] ?? ""; echo "<p>留言:" . htmlspecialchars($msg) . "</p>"; ?>

錯誤訊息設計:既要清楚,又要避免洩露細節

  • 給用戶看的訊息:指出哪個欄位不符合要求,以及如何修正(例如「密碼最少 8 字元」)。
  • 避免洩露:不要直接輸出伺服器路徑、資料庫錯誤全文、或系統堆疊追蹤。
  • 給開發者看的細節:可記錄到伺服器日誌(本課程先理解概念即可)。

Checkpoint:延伸課題(≥40 題)

本小測以四選一為主,涵蓋:白名單驗證、輸出前處理(XSS 概念)、以及錯誤訊息的設計原則。

✍️頁末 20 題 Coding(一行一題)

每題均提供:提示/核對答案/顯示參考答案/講解。請在模擬器內完成代碼,然後按「核對答案」。

代碼題 1:表單(text):問候語
代碼題 2:表單(password):只顯示密碼長度
代碼題 3:表單(date):輸出生日
代碼題 4:下拉式選單:顯示班別
代碼題 5:複選框:列出興趣(foreach)
代碼題 6:GET 搜尋:從 URL 取得 q
代碼題 7:POST 登入:必填檢查
代碼題 8:isset():欄位是否存在
代碼題 9:empty():必填欄位
代碼題 10:is_numeric():年齡必須為數字
代碼題 11:strlen():密碼最少 8 字元
代碼題 12:in_array():白名單驗證下拉值
代碼題 13:strpos():電郵必須包含 @
代碼題 14:曲奇:記住使用者名稱 1 天
代碼題 15:曲奇:清除指定 cookie
代碼題 16:Session:登入後建立已登入狀態
代碼題 17:Session:未登入則導回登入頁
代碼題 18:登出:清除 Session
代碼題 19:同一處理邏輯支援 GET/POST
代碼題 20:綜合:提交→有效性檢驗→成功才設定 Session