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

PHP 原生註冊登入系統實作:表單驗證、密碼雜湊、Session 管理、SQL 注入防護

     編輯:PHP 綜合知識

零框架、原生 PHP + MySQL 實作完整註冊/登入系統,涵蓋表單驗證、password_hash 密碼雜湊、Session 狀態管理、Prepared Statements 防 SQL 注入、XSS 防護,適合理解認證核心流程。

資料庫設計

CREATE DATABASE auth_demo DEFAULT CHARSET utf8mb4;
USE auth_demo;
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;

1. 連線檔 db.php

<?php
$mysqli = new mysqli('127.0.0.1', 'root', '', 'auth_demo');
if ($mysqli->connect_errno) die('DB 連線失敗');
$mysqli->set_charset('utf8mb4');
// 開啟嚴格模式
$mysqli->query("SET sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION'");
?>

2. 註冊 register.php

<?php
require 'db.php';
session_start();
$errors = [];

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = trim($_POST['username'] ?? '');
    $password = $_POST['password'] ?? '';
    $confirm  = $_POST['confirm'] ?? '';

    // 驗證
    if (!$username || !$password) $errors[] = '帳號密碼不可為空';
    if ($password !== $confirm) $errors[] = '兩次密碼不一致';
    if (strlen($password) < 8) $errors[] = '密碼至少 8 字符';
    if (!preg_match('/[A-Za-z]/', $password) || !preg_match('/\d/', $password)) {
        $errors[] = '密碼需含字母與數字';
    }

    // 檢查用戶名是否存在
    if (empty($errors)) {
        $stmt = $mysqli->prepare('SELECT id FROM users WHERE username = ?');
        $stmt->bind_param('s', $username);
        $stmt->execute();
        if ($stmt->get_result()->num_rows > 0) {
            $errors[] = '帳號已被註冊';
        }
        $stmt->close();
    }

    // 寫入
    if (empty($errors)) {
        $hash = password_hash($password, PASSWORD_DEFAULT); // Bcrypt cost=10
        $stmt = $mysqli->prepare('INSERT INTO users (username, password_hash) VALUES (?, ?)');
        $stmt->bind_param('ss', $username, $hash);
        if ($stmt->execute()) {
            $_SESSION['success'] = '註冊成功,請登入';
            header('Location: login.php');
            exit;
        } else {
            $errors[] = '註冊失敗,請重試';
        }
        $stmt->close();
    }
}
?>
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>註冊</title></head><body>
<h1>註冊</h1>
<?php if ($errors): ?><ul style="color:red"><?php foreach ($errors as $e) echo "
  • $e
  • "; ?></ul><?php endif; ?> <form method="post"> 帳號: <input type="text" name="username" required><br><br> 密碼: <input type="password" name="password" required><br><br> 確認: <input type="password" name="confirm" required><br><br> <button type="submit">註冊</button> </form> <p><a href="login.php">已有帳號?去登入</a></p> </body></html>

    3. 登入 login.php

    <?php
    require 'db.php';
    session_start();
    $error = '';
    
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $username = trim($_POST['username'] ?? '');
        $password = $_POST['password'] ?? '';
    
        if ($username && $password) {
            $stmt = $mysqli->prepare('SELECT id, password_hash FROM users WHERE username = ?');
            $stmt->bind_param('s', $username);
            $stmt->execute();
            $user = $stmt->get_result()->fetch_assoc();
            $stmt->close();
    
            if ($user && password_verify($password, $user['password_hash'])) {
                // 登入成功,建立 Session
                session_regenerate_id(true); // 防 Session Fixation
                $_SESSION['user_id'] = $user['id'];
                $_SESSION['username'] = $username;
                header('Location: dashboard.php');
                exit;
            }
        }
        $error = '帳號或密碼錯誤';
    }
    ?>
    <!DOCTYPE html><html><head><meta charset="UTF-8"><title>登入</title></head><body>
    <h1>登入</h1>
    <?php if ($error) echo "

    $error

    "; ?> <form method="post"> 帳號: <input type="text" name="username" required><br><br> 密碼: <input type="password" name="password" required><br><br> <button type="submit">登入</button> </form> <p><a href="register.php">註冊新帳號</a></p> </body></html>

    4. 受保護頁面 dashboard.php

    <?php
    session_start();
    if (empty($_SESSION['user_id'])) {
        header('Location: login.php');
        exit;
    }
    require 'db.php';
    $stmt = $mysqli->prepare('SELECT username FROM users WHERE id = ?');
    $stmt->bind_param('i', $_SESSION['user_id']);
    $stmt->execute();
    $user = $stmt->get_result()->fetch_assoc();
    ?>
    <!DOCTYPE html><html><head><meta charset="UTF-8"><title>儀表板</title></head><body>
    <h1>歡迎, <?= htmlspecialchars($user['username']) ?></h1>
    <p><a href="logout.php">登出</a></p>
    </body></html>

    5. 登出 logout.php

    <?php
    session_start();
    $_SESSION = [];
    session_destroy();
    header('Location: login.php');
    ?>

    安全核心清單

    1. 密碼雜湊:password_hash(PASSWORD_DEFAULT) → Bcrypt,自動鹽值、Cost 可升級。
    2. Prepared Statements:所有 SQL 使用 prepare/bind_param,徹底防注入。
    3. 3. Session 安全:session_regenerate_id(true) 登入後換 ID、session.cookie_httponly=1、session.cookie_secure=1 (HTTPS)。 4. XSS 防護:輸出變數用 htmlspecialchars()。 5. CSRF 保護:表單加入 $_SESSION['csrf'] = bin2hex(random_bytes(32)) 驗證(此處簡化省略)。 6. 暴力破解防禦:登入失敗計數 + 延遲/鎖定(可用 Redis 計數器)。

    結語

    認證系統核心只有三步:雜湊存儲 → 驗證比對 → Session 維持。掌握 password_hash/verify、mysqli prepare、session 三大支柱,框架封裝的 Auth 組件才不會變成黑盒。

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