文章

PHP - 使用者驗證系統設計


課程簡介

使用者驗證系統是網站安全與功能的基礎,主要用於管理使用者登入、註冊、登出等操作。本課程將教學如何利用 PHP 與 MySQL 實現一個簡單且安全的使用者驗證系統,包括密碼加密、登入狀態維護與安全性防護。


使用者驗證系統的基本流程

  1. 使用者註冊:收集使用者資訊並存入資料庫。
  2. 使用者登入:驗證輸入的帳號與密碼是否匹配資料庫。
  3. 登入狀態維護:利用 Session 或 Cookie 記錄使用者狀態。
  4. 安全性防護:包括密碼加密、避免 SQL 注入、防止暴力破解等。

設計步驟

1. 資料庫結構

建立一個儲存使用者資料的資料表:

1
2
3
4
5
6
7
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL UNIQUE,
    email VARCHAR(100) NOT NULL UNIQUE,
    password VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

2. 註冊功能

後端程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
if ($_SERVER["REQUEST_METHOD"] === "POST") {
    $username = $_POST["username"];
    $email = $_POST["email"];
    $password = $_POST["password"];
    
    // 驗證輸入
    if (empty($username) || empty($email) || empty($password)) {
        die("所有欄位皆為必填!");
    }

    // 密碼加密
    $hashed_password = password_hash($password, PASSWORD_DEFAULT);

    // 儲存至資料庫
    $conn = new mysqli("localhost", "root", "", "auth_demo");
    if ($conn->connect_error) {
        die("連接失敗:" . $conn->connect_error);
    }

    $stmt = $conn->prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)");
    $stmt->bind_param("sss", $username, $email, $hashed_password);
    if ($stmt->execute()) {
        echo "註冊成功!";
    } else {
        echo "註冊失敗:" . $conn->error;
    }
    $stmt->close();
    $conn->close();
}
?>
<form method="post">
    <input type="text" name="username" placeholder="使用者名稱"><br>
    <input type="email" name="email" placeholder="電子郵件"><br>
    <input type="password" name="password" placeholder="密碼"><br>
    <button type="submit">註冊</button>
</form>

3. 登入功能

後端程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?php
session_start();

if ($_SERVER["REQUEST_METHOD"] === "POST") {
    $username = $_POST["username"];
    $password = $_POST["password"];

    // 驗證輸入
    if (empty($username) || empty($password)) {
        die("所有欄位皆為必填!");
    }

    // 資料庫查詢
    $conn = new mysqli("localhost", "root", "", "auth_demo");
    if ($conn->connect_error) {
        die("連接失敗:" . $conn->connect_error);
    }

    $stmt = $conn->prepare("SELECT id, password FROM users WHERE username = ?");
    $stmt->bind_param("s", $username);
    $stmt->execute();
    $stmt->store_result();
    if ($stmt->num_rows > 0) {
        $stmt->bind_result($id, $hashed_password);
        $stmt->fetch();
        if (password_verify($password, $hashed_password)) {
            $_SESSION["user_id"] = $id;
            echo "登入成功!";
        } else {
            echo "密碼錯誤!";
        }
    } else {
        echo "使用者不存在!";
    }
    $stmt->close();
    $conn->close();
}
?>
<form method="post">
    <input type="text" name="username" placeholder="使用者名稱"><br>
    <input type="password" name="password" placeholder="密碼"><br>
    <button type="submit">登入</button>
</form>

4. 登出功能

後端程式碼:

1
2
3
4
5
6
<?php
session_start();
session_unset();
session_destroy();
echo "已成功登出!";
?>

5. 驗證登入狀態

在需要保護的頁面中檢查是否已登入:

1
2
3
4
5
6
7
<?php
session_start();
if (!isset($_SESSION["user_id"])) {
    die("請先登入!");
}
echo "歡迎進入保護頁面!";
?>

安全性強化

1. 密碼加密

  • 使用 password_hash() 進行密碼加密。
  • 驗證密碼時使用 password_verify()

2. 防止 SQL 注入

使用準備語句(Prepared Statements)。

3. 限制登入嘗試次數

紀錄 IP 或用戶名稱的失敗次數,超過限制後暫時封鎖:

1
// 範例:封鎖超過 5 次失敗登入嘗試

4. 使用 HTTPS 傳輸

確保所有資料傳輸都經過加密的 HTTPS 連線。


教學練習

練習 1:基本登入系統

設計一個能夠註冊、登入及登出的簡單使用者驗證系統。


練習 2:忘記密碼功能

新增「忘記密碼」功能,實現透過電子郵件重設密碼。


練習 3:保持登入狀態

使用 Cookie 儲存使用者登入資訊,實現「記住我」功能。


教學重點

  • 理解使用者驗證系統的基礎架構與設計原則。
  • 掌握密碼加密與驗證、登入狀態管理等核心技術。
  • 學習如何強化系統安全性,避免常見漏洞如 SQL 注入與暴力破解。

本文章以 CC BY 4.0 授權