PHP用户登录验证系统实现教程 – 安全认证开发指南

2025-09-12 0 1,029

1. 系统概述

用户登录系统是Web应用的基础功能之一。本教程将指导您创建一个安全可靠的PHP登录系统,包含以下功能:

  • 用户注册与数据验证
  • 安全的密码加密存储
  • 登录状态与会话管理
  • 防止SQL注入和XSS攻击
  • 记住登录状态功能

2. 数据库设计

首先创建用户表存储用户信息:

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

3. 数据库连接

创建数据库连接文件config.php:

<?php
$host = 'localhost';
$dbname = 'your_database';
$username = 'your_username';
$password = 'your_password';

try {
    $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $username, $password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch (PDOException $e) {
    die("数据库连接失败: " . $e->getMessage());
}
?>
    

4. 用户注册功能

创建注册页面register.php:

<?php
require_once 'config.php';
session_start();

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) || strlen($username) < 3) {
        $errors[] = "用户名至少需要3个字符";
    }
    
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors[] = "请输入有效的邮箱地址";
    }
    
    if (strlen($password) prepare("SELECT id FROM users WHERE username = ? OR email = ?");
        $stmt->execute([$username, $email]);
        
        if ($stmt->rowCount() > 0) {
            $errors[] = "用户名或邮箱已被注册";
        }
    }
    
    // 如果没有错误,创建用户
    if (empty($errors)) {
        $hashed_password = password_hash($password, PASSWORD_DEFAULT);
        
        $stmt = $pdo->prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)");
        if ($stmt->execute([$username, $email, $hashed_password])) {
            $_SESSION['success_msg'] = "注册成功,请登录";
            header("Location: login.php");
            exit();
        } else {
            $errors[] = "注册失败,请稍后重试";
        }
    }
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>用户注册</title>
</head>
<body>
    <h2>用户注册</h2>
    
    <?php if (!empty($errors)): ?>
        <div class="errors">
            <?php foreach ($errors as $error): ?>
                <p><?php echo htmlspecialchars($error); ?></p>
            <?php endforeach; ?>
        </div>
    <?php endif; ?>
    
    <form method="post" action="">
        <div>
            <label>用户名:</label>
            <input type="text" name="username" required value="<?php echo isset($username) ? htmlspecialchars($username) : ''; ?>">
        </div>
        
        <div>
            <label>邮箱:</label>
            <input type="email" name="email" required value="<?php echo isset($email) ? htmlspecialchars($email) : ''; ?>">
        </div>
        
        <div>
            <label>密码:</label>
            <input type="password" name="password" required>
        </div>
        
        <div>
            <label>确认密码:</label>
            <input type="password" name="confirm_password" required>
        </div>
        
        <div>
            <button type="submit">注册</button>
        </div>
    </form>
    
    <p>已有账号? <a href="login.php" rel="external nofollow" >立即登录</a></p>
</body>
</html>
    

5. 用户登录功能

创建登录页面login.php:

<?php
require_once 'config.php';
session_start();

// 如果用户已登录,重定向到主页
if (isset($_SESSION['user_id'])) {
    header("Location: index.php");
    exit();
}

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 FROM users WHERE username = ? OR email = ?");
        $stmt->execute([$username, $username]);
        $user = $stmt->fetch();
        
        if ($user && password_verify($password, $user['password'])) {
            // 登录成功
            $_SESSION['user_id'] = $user['id'];
            $_SESSION['username'] = $user['username'];
            
            // 更新最后登录时间
            $stmt = $pdo->prepare("UPDATE users SET last_login = NOW() WHERE id = ?");
            $stmt->execute([$user['id']]);
            
            // 记住登录状态
            if ($remember) {
                $token = bin2hex(random_bytes(32));
                $expire = time() + 60 * 60 * 24 * 30; // 30天
                
                setcookie('remember_token', $token, $expire, '/');
                
                // 存储token到数据库
                $stmt = $pdo->prepare("UPDATE users SET remember_token = ? WHERE id = ?");
                $stmt->execute([$token, $user['id']]);
            }
            
            header("Location: index.php");
            exit();
        } else {
            $errors[] = "用户名或密码错误";
        }
    }
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>用户登录</title>
</head>
<body>
    <h2>用户登录</h2>
    
    <?php if (isset($_SESSION['success_msg'])): ?>
        <div class="success">
            <p><?php echo htmlspecialchars($_SESSION['success_msg']); unset($_SESSION['success_msg']); ?></p>
        </div>
    <?php endif; ?>
    
    <?php if (!empty($errors)): ?>
        <div class="errors">
            <?php foreach ($errors as $error): ?>
                <p><?php echo htmlspecialchars($error); ?></p>
            <?php endforeach; ?>
        </div>
    <?php endif; ?>
    
    <form method="post" action="">
        <div>
            <label>用户名或邮箱:</label>
            <input type="text" name="username" required value="<?php echo isset($username) ? htmlspecialchars($username) : ''; ?>">
        </div>
        
        <div>
            <label>密码:</label>
            <input type="password" name="password" required>
        </div>
        
        <div>
            <label>
                <input type="checkbox" name="remember"> 记住我
            </label>
        </div>
        
        <div>
            <button type="submit">登录</button>
        </div>
    </form>
    
    <p>还没有账号? <a href="register.php" rel="external nofollow" >立即注册</a></p>
</body>
</html>
    

6. 会话管理与自动登录

创建session.php文件处理会话和自动登录:

<?php
require_once 'config.php';

session_start();

// 自动登录功能
function auto_login() {
    global $pdo;
    
    if (isset($_COOKIE['remember_token']) && !isset($_SESSION['user_id'])) {
        $token = $_COOKIE['remember_token'];
        
        $stmt = $pdo->prepare("SELECT id, username FROM users WHERE remember_token = ?");
        $stmt->execute([$token]);
        $user = $stmt->fetch();
        
        if ($user) {
            $_SESSION['user_id'] = $user['id'];
            $_SESSION['username'] = $user['username'];
        }
    }
}

// 检查用户是否登录
function is_logged_in() {
    return isset($_SESSION['user_id']);
}

// 获取当前用户ID
function get_current_user_id() {
    return $_SESSION['user_id'] ?? null;
}

// 注销功能
function logout() {
    global $pdo;
    
    if (isset($_SESSION['user_id'])) {
        // 清除数据库中的remember_token
        $stmt = $pdo->prepare("UPDATE users SET remember_token = NULL WHERE id = ?");
        $stmt->execute([$_SESSION['user_id']]);
    }
    
    // 清除会话
    $_SESSION = [];
    session_destroy();
    
    // 清除记住登录的cookie
    setcookie('remember_token', '', time() - 3600, '/');
}

// 调用自动登录
auto_login();
?>
    

7. 主页与用户仪表板

创建主页index.php:

<?php
require_once 'session.php';

if (!is_logged_in()) {
    header("Location: login.php");
    exit();
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>用户主页</title>
</head>
<body>
    <h2>欢迎, <?php echo htmlspecialchars($_SESSION['username']); ?>!</h2>
    
    <nav>
        <ul>
            <li><a href="profile.php" rel="external nofollow" >个人资料</a></li>
            <li><a href="logout.php" rel="external nofollow" >退出登录</a></li>
        </ul>
    </nav>
    
    <div>
        <h3>用户仪表板</h3>
        <p>这是您的个人主页,您可以在这里管理您的账户信息。</p>
    </div>
</body>
</html>
    

8. 安全增强措施

为了提高系统安全性,我们需要实施以下措施:

8.1 防止SQL注入

始终使用预处理语句:

// 不安全的做法
$sql = "SELECT * FROM users WHERE username = '$username'";
$result = $pdo->query($sql);

// 安全的做法 - 使用预处理语句
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
    

8.2 防止XSS攻击

对所有用户输出进行转义:

// 不安全的做法
echo $user_input;

// 安全的做法
echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
    

8.3 密码加密

使用password_hash()和password_verify()函数:

// 创建密码哈希
$hashed_password = password_hash($password, PASSWORD_DEFAULT);

// 验证密码
if (password_verify($input_password, $hashed_password)) {
    // 密码正确
}
    

8.4 CSRF保护

在表单中添加CSRF令牌:

// 生成CSRF令牌
if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

// 在表单中包含令牌
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">

// 验证令牌
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
    die("CSRF令牌验证失败");
}
    

9. 完整系统文件结构

/login-system/
│
├── config.php          # 数据库配置
├── session.php         # 会话管理
├── register.php        # 用户注册
├── login.php           # 用户登录
├── index.php           # 主页
├── profile.php         # 用户资料页面
├── logout.php          # 退出登录
└── .htaccess          # Apache配置(可选)
    

10. 总结

本教程详细介绍了如何使用PHP创建一个完整的用户登录验证系统。我们实现了用户注册、登录、会话管理和安全防护等功能。关键点包括:

  • 使用预处理语句防止SQL注入
  • 对输出进行转义防止XSS攻击
  • 使用password_hash()安全加密密码
  • 实现CSRF令牌保护
  • 提供”记住我”功能增强用户体验

通过遵循这些最佳实践,您可以创建一个安全可靠的用户认证系统,为您的Web应用提供坚实的基础。记得根据实际需求调整和扩展这些功能,并始终保持对安全问题的关注。

PHP用户登录验证系统实现教程 - 安全认证开发指南
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

淘吗网 php PHP用户登录验证系统实现教程 – 安全认证开发指南 https://www.taomawang.com/server/php/1063.html

下一篇:

已经没有下一篇了!

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务