PHP项目如何实现用户登录?

wen PHP项目 13

本文目录导读:

PHP项目如何实现用户登录?

  1. 数据库设计
  2. 注册功能(创建用户)
  3. 登录功能
  4. 会话验证(保护页面)
  5. 使用示例
  6. 退出登录
  7. 数据库连接配置
  8. 安全最佳实践

我来详细说明PHP项目实现用户登录的完整流程,包括安全最佳实践:

数据库设计

首先创建用户表:

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

注册功能(创建用户)

// register.php
<?php
require_once 'config.php'; // 数据库连接配置
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = trim($_POST['username']);
    $email = trim($_POST['email']);
    $password = $_POST['password'];
    $confirm_password = $_POST['confirm_password'];
    // 验证输入
    $errors = [];
    if (empty($username)) $errors[] = '用户名不能为空';
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = '邮箱格式不正确';
    if (strlen($password) < 8) $errors[] = '密码至少8位';
    if ($password !== $confirm_password) $errors[] = '两次密码不一致';
    if (empty($errors)) {
        // 检查用户是否已存在
        $stmt = $pdo->prepare("SELECT id FROM users WHERE username = ? OR email = ?");
        $stmt->execute([$username, $email]);
        if ($stmt->fetch()) {
            $errors[] = '用户名或邮箱已存在';
        } else {
            // 密码哈希存储
            $password_hash = password_hash($password, PASSWORD_DEFAULT);
            $stmt = $pdo->prepare("INSERT INTO users (username, email, password_hash) VALUES (?, ?, ?)");
            if ($stmt->execute([$username, $email, $password_hash])) {
                header('Location: login.php?registered=1');
                exit;
            } else {
                $errors[] = '注册失败,请重试';
            }
        }
    }
}
?>
<!-- 注册表单 -->
<form method="POST">
    <input type="text" name="username" placeholder="用户名" required>
    <input type="email" name="email" placeholder="邮箱" required>
    <input type="password" name="password" placeholder="密码" required minlength="8">
    <input type="password" name="confirm_password" placeholder="确认密码" required>
    <button type="submit">注册</button>
    <?php if (!empty($errors)): ?>
        <div class="errors">
            <?php foreach ($errors as $error): ?>
                <p><?= htmlspecialchars($error) ?></p>
            <?php endforeach; ?>
        </div>
    <?php endif; ?>
</form>

登录功能

// login.php
<?php
session_start();
require_once 'config.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = trim($_POST['username']);
    $password = $_POST['password'];
    $remember = isset($_POST['remember']);
    $errors = [];
    if (empty($username)) $errors[] = '请输入用户名/邮箱';
    if (empty($password)) $errors[] = '请输入密码';
    if (empty($errors)) {
        // 查询用户(支持用户名或邮箱登录)
        $stmt = $pdo->prepare("SELECT id, username, password_hash FROM users 
                               WHERE username = ? OR email = ?");
        $stmt->execute([$username, $username]);
        $user = $stmt->fetch();
        if ($user && password_verify($password, $user['password_hash'])) {
            // 登录成功:设置Session
            $_SESSION['user_id'] = $user['id'];
            $_SESSION['username'] = $user['username'];
            $_SESSION['login_time'] = time();
            // "记住我"功能
            if ($remember) {
                $token = bin2hex(random_bytes(32));
                $expires = date('Y-m-d H:i:s', strtotime('+30 days'));
                // 存储token到数据库
                $stmt = $pdo->prepare("INSERT INTO login_tokens (user_id, token, expires_at) 
                                       VALUES (?, ?, ?)");
                $stmt->execute([$user['id'], $token, $expires]);
                // 设置Cookie
                setcookie('remember_token', $token, strtotime('+30 days'), '/', '', true, true);
            }
            // 重定向到首页
            header('Location: index.php');
            exit;
        } else {
            $errors[] = '用户名/邮箱或密码错误';
        }
    }
}
?>
<!-- 登录表单 -->
<form method="POST" action="login.php">
    <input type="text" name="username" placeholder="用户名或邮箱" required>
    <input type="password" name="password" placeholder="密码" required>
    <label>
        <input type="checkbox" name="remember"> 记住我
    </label>
    <button type="submit">登录</button>
    <?php if (!empty($errors)): ?>
        <div class="errors">
            <?php foreach ($errors as $error): ?>
                <p><?= htmlspecialchars($error) ?></p>
            <?php endforeach; ?>
        </div>
    <?php endif; ?>
</form>

会话验证(保护页面)

// auth_check.php - 用于需要登录的页面
<?php
session_start();
function isLoggedIn() {
    if (isset($_SESSION['user_id'])) {
        return true;
    }
    // 检查"记住我"的Cookie
    if (isset($_COOKIE['remember_token'])) {
        $token = $_COOKIE['remember_token'];
        global $pdo;
        $stmt = $pdo->prepare("SELECT user_id, expires_at FROM login_tokens 
                               WHERE token = ? AND expires_at > NOW()");
        $stmt->execute([$token]);
        $token_data = $stmt->fetch();
        if ($token_data) {
            // 恢复Session
            $stmt = $pdo->prepare("SELECT id, username FROM users WHERE id = ?");
            $stmt->execute([$token_data['user_id']]);
            $user = $stmt->fetch();
            if ($user) {
                $_SESSION['user_id'] = $user['id'];
                $_SESSION['username'] = $user['username'];
                return true;
            }
        }
        // 无效token,清除Cookie
        setcookie('remember_token', '', time() - 3600, '/');
    }
    return false;
}
function requireLogin() {
    if (!isLoggedIn()) {
        header('Location: login.php?redirect=' . urlencode($_SERVER['REQUEST_URI']));
        exit;
    }
}
?>

使用示例

// profile.php - 需要登录的页面
<?php
require_once 'auth_check.php';
requireLogin();
echo "欢迎您, " . htmlspecialchars($_SESSION['username']) . "!";
?>

退出登录

// logout.php
<?php
session_start();
// 清除所有Session变量
$_SESSION = array();
// 清除Session Cookie
if (ini_get("session.use_cookies")) {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
}
// 清除记住我的Cookie和数据库记录
if (isset($_COOKIE['remember_token'])) {
    $token = $_COOKIE['remember_token'];
    global $pdo;
    $stmt = $pdo->prepare("DELETE FROM login_tokens WHERE token = ?");
    $stmt->execute([$token]);
    setcookie('remember_token', '', time() - 3600, '/');
}
session_destroy();
header('Location: login.php?logged_out=1');
exit;
?>

数据库连接配置

// config.php
<?php
$host = 'localhost';
$dbname = 'your_database';
$username = 'your_username';
$password = 'your_password';
try {
    $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch(PDOException $e) {
    die("数据库连接失败: " . $e->getMessage());
}
?>

安全最佳实践

  1. 密码存储:使用 password_hash()password_verify()
  2. 输入验证:始终验证和清理用户输入
  3. 输出编码:使用 htmlspecialchars() 防止XSS
  4. SQL注入防护:使用预处理语句(PDO)
  5. Session安全:设置 session.cookie_httponlysession.cookie_secure
  6. CSRF防护:在表单中添加token验证
  7. HTTPS:生产环境必须使用HTTPS
  8. 登录限制:限制登录尝试次数防止暴力破解

这是一个完整的用户登录系统实现,包含了注册、登录、会话管理、"记住我"功能和退出功能,根据项目需求,你可以添加验证码、邮箱验证、密码重置等功能来增强安全性。

抱歉,评论功能暂时关闭!