Skip to content

14.2 实战 2:用户注册登录系统

本章节将实现一个完整的用户注册登录系统,包括用户注册、登录、退出功能。

项目结构

user-auth-system/
├── db.php              # 数据库连接文件
├── index.php           # 首页
├── register.php        # 注册页面
├── login.php           # 登录页面
├── logout.php          # 退出登录
├── profile.php         # 个人资料页面
└── css/
    └── style.css       # 样式文件

1. 数据库配置

创建 db.php 文件,用于数据库连接:

php
<?php
// db.php
function getDbConnection() {
    $servername = "localhost";
    $username = "root";
    $password = "";
    $dbname = "php_tutorial";
    
    // 创建连接
    $conn = new mysqli($servername, $username, $password, $dbname);
    
    // 检查连接
    if ($conn->connect_error) {
        die("连接失败: " . $conn->connect_error);
    }
    
    // 设置字符集
    $conn->set_charset("utf8mb4");
    
    return $conn;
}
?>

2. 数据库表结构

创建 users 表:

sql
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
);

3. 样式文件

创建 css/style.css 文件:

css
/* style.css */
* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    font-family: Arial, sans-serif;
    line-height: 1.6;
    color: #333;
    background-color: #f4f4f4;
}

.container {
    max-width: 500px;
    margin: 0 auto;
    padding: 20px;
}

h1 {
    text-align: center;
    color: #333;
    margin-bottom: 30px;
}

h2 {
    text-align: center;
    color: #333;
    margin-bottom: 20px;
}

.form {
    background-color: #fff;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.form-group {
    margin-bottom: 15px;
}

label {
    display: block;
    margin-bottom: 5px;
    font-weight: bold;
}

input[type="text"],
input[type="email"],
input[type="password"] {
    width: 100%;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 16px;
}

button[type="submit"] {
    background-color: #4CAF50;
    color: white;
    padding: 10px 20px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 16px;
    width: 100%;
    margin-top: 10px;
}

button[type="submit"]:hover {
    background-color: #45a049;
}

.error {
    background-color: #f8d7da;
    color: #721c24;
    padding: 10px;
    border-radius: 4px;
    margin-bottom: 15px;
    border: 1px solid #f5c6cb;
}

.success {
    background-color: #d4edda;
    color: #155724;
    padding: 10px;
    border-radius: 4px;
    margin-bottom: 15px;
    border: 1px solid #c3e6cb;
}

.link {
    text-align: center;
    margin-top: 20px;
}

.link a {
    color: #4CAF50;
    text-decoration: none;
}

.link a:hover {
    text-decoration: underline;
}

.navbar {
    background-color: #333;
    color: white;
    padding: 10px 0;
    margin-bottom: 30px;
}

.navbar .container {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.navbar a {
    color: white;
    text-decoration: none;
    margin: 0 10px;
}

.navbar a:hover {
    text-decoration: underline;
}

.profile {
    background-color: #fff;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    text-align: center;
}

.profile h2 {
    margin-bottom: 20px;
}

.profile p {
    margin: 10px 0;
    font-size: 16px;
}

4. 首页

创建 index.php 文件:

php
<?php
// index.php
session_start();
?>

<!DOCTYPE html>
<html>
<head>
    <title>首页</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <!-- 导航栏 -->
    <div class="navbar">
        <div class="container">
            <div class="logo">
                <h3>用户系统</h3>
            </div>
            <div class="nav-links">
                <?php if (isset($_SESSION['user_id'])): ?>
                    <a href="profile.php">个人资料</a>
                    <a href="logout.php">退出登录</a>
                <?php else: ?>
                    <a href="login.php">登录</a>
                    <a href="register.php">注册</a>
                <?php endif; ?>
            </div>
        </div>
    </div>
    
    <div class="container">
        <h1>欢迎来到用户系统</h1>
        
        <?php if (isset($_SESSION['user_id'])): ?>
            <div class="success">
                您已登录,欢迎回来!
            </div>
        <?php else: ?>
            <div class="form">
                <h2>请登录或注册</h2>
                <p>这是一个用户注册登录系统的示例</p>
                <div class="link">
                    <a href="login.php">登录</a> | <a href="register.php">注册</a>
                </div>
            </div>
        <?php endif; ?>
    </div>
</body>
</html>

5. 注册页面

创建 register.php 文件:

php
<?php
// register.php
session_start();

// 如果已登录,跳转到首页
if (isset($_SESSION['user_id'])) {
    header('Location: index.php');
    exit;
}

$error = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['register'])) {
    require_once 'db.php';
    $conn = getDbConnection();
    
    // 获取表单数据
    $username = $_POST['username'];
    $email = $_POST['email'];
    $password = $_POST['password'];
    $confirmPassword = $_POST['confirm_password'];
    
    // 验证数据
    if (empty($username) || empty($email) || empty($password) || empty($confirmPassword)) {
        $error = '所有字段都不能为空';
    } elseif ($password !== $confirmPassword) {
        $error = '两次输入的密码不一致';
    } elseif (strlen($password) < 6) {
        $error = '密码长度至少为6位';
    } else {
        // 检查用户名是否已存在
        $stmt = $conn->prepare("SELECT id FROM users WHERE username = ?");
        $stmt->bind_param("s", $username);
        $stmt->execute();
        $result = $stmt->get_result();
        
        if ($result->num_rows > 0) {
            $error = '用户名已存在';
        } else {
            // 检查邮箱是否已存在
            $stmt = $conn->prepare("SELECT id FROM users WHERE email = ?");
            $stmt->bind_param("s", $email);
            $stmt->execute();
            $result = $stmt->get_result();
            
            if ($result->num_rows > 0) {
                $error = '邮箱已被注册';
            } else {
                // 密码加密
                $hashedPassword = password_hash($password, PASSWORD_DEFAULT);
                
                // 插入用户数据
                $stmt = $conn->prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)");
                $stmt->bind_param("sss", $username, $email, $hashedPassword);
                
                if ($stmt->execute()) {
                    header('Location: login.php?success=注册成功,请登录');
                    exit;
                } else {
                    $error = '注册失败,请重试';
                }
            }
        }
        
        $stmt->close();
    }
    
    $conn->close();
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>注册</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <!-- 导航栏 -->
    <div class="navbar">
        <div class="container">
            <div class="logo">
                <h3>用户系统</h3>
            </div>
            <div class="nav-links">
                <a href="index.php">首页</a>
                <a href="login.php">登录</a>
            </div>
        </div>
    </div>
    
    <div class="container">
        <h1>用户注册</h1>
        
        <div class="form">
            <?php if (!empty($error)): ?>
                <div class="error"><?php echo $error; ?></div>
            <?php endif; ?>
            
            <form action="" method="post">
                <div class="form-group">
                    <label>用户名: <input type="text" name="username" required></label>
                </div>
                <div class="form-group">
                    <label>邮箱: <input type="email" name="email" required></label>
                </div>
                <div class="form-group">
                    <label>密码: <input type="password" name="password" required></label>
                </div>
                <div class="form-group">
                    <label>确认密码: <input type="password" name="confirm_password" required></label>
                </div>
                <button type="submit" name="register">注册</button>
            </form>
            
            <div class="link">
                已有账号?<a href="login.php">立即登录</a>
            </div>
        </div>
    </div>
</body>
</html>

6. 登录页面

创建 login.php 文件:

php
<?php
// login.php
session_start();

// 如果已登录,跳转到首页
if (isset($_SESSION['user_id'])) {
    header('Location: index.php');
    exit;
}

$error = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['login'])) {
    require_once 'db.php';
    $conn = getDbConnection();
    
    // 获取表单数据
    $username = $_POST['username'];
    $password = $_POST['password'];
    
    // 验证数据
    if (empty($username) || empty($password)) {
        $error = '用户名和密码不能为空';
    } else {
        // 查找用户
        $stmt = $conn->prepare("SELECT id, username, email, password FROM users WHERE username = ?");
        $stmt->bind_param("s", $username);
        $stmt->execute();
        $result = $stmt->get_result();
        
        if ($result->num_rows > 0) {
            $user = $result->fetch_assoc();
            
            // 验证密码
            if (password_verify($password, $user['password'])) {
                // 设置会话
                $_SESSION['user_id'] = $user['id'];
                $_SESSION['username'] = $user['username'];
                $_SESSION['email'] = $user['email'];
                
                header('Location: index.php');
                exit;
            } else {
                $error = '密码错误';
            }
        } else {
            $error = '用户名不存在';
        }
        
        $stmt->close();
    }
    
    $conn->close();
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>登录</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <!-- 导航栏 -->
    <div class="navbar">
        <div class="container">
            <div class="logo">
                <h3>用户系统</h3>
            </div>
            <div class="nav-links">
                <a href="index.php">首页</a>
                <a href="register.php">注册</a>
            </div>
        </div>
    </div>
    
    <div class="container">
        <h1>用户登录</h1>
        
        <div class="form">
            <?php if (isset($_GET['success'])): ?>
                <div class="success"><?php echo $_GET['success']; ?></div>
            <?php endif; ?>
            
            <?php if (!empty($error)): ?>
                <div class="error"><?php echo $error; ?></div>
            <?php endif; ?>
            
            <form action="" method="post">
                <div class="form-group">
                    <label>用户名: <input type="text" name="username" required></label>
                </div>
                <div class="form-group">
                    <label>密码: <input type="password" name="password" required></label>
                </div>
                <button type="submit" name="login">登录</button>
            </form>
            
            <div class="link">
                没有账号?<a href="register.php">立即注册</a>
            </div>
        </div>
    </div>
</body>
</html>

7. 个人资料页面

创建 profile.php 文件:

php
<?php
// profile.php
session_start();

// 检查是否登录
if (!isset($_SESSION['user_id'])) {
    header('Location: login.php');
    exit;
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>个人资料</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <!-- 导航栏 -->
    <div class="navbar">
        <div class="container">
            <div class="logo">
                <h3>用户系统</h3>
            </div>
            <div class="nav-links">
                <a href="index.php">首页</a>
                <a href="logout.php">退出登录</a>
            </div>
        </div>
    </div>
    
    <div class="container">
        <h1>个人资料</h1>
        
        <div class="profile">
            <h2>欢迎,<?php echo $_SESSION['username']; ?></h2>
            <p><strong>用户名:</strong> <?php echo $_SESSION['username']; ?></p>
            <p><strong>邮箱:</strong> <?php echo $_SESSION['email']; ?></p>
            <p><strong>用户ID:</strong> <?php echo $_SESSION['user_id']; ?></p>
            <div class="link" style="margin-top: 30px;">
                <a href="logout.php">退出登录</a>
            </div>
        </div>
    </div>
</body>
</html>

8. 退出登录

创建 logout.php 文件:

php
<?php
// logout.php
session_start();

// 清除会话变量
session_unset();

// 销毁会话
session_destroy();

// 跳转到登录页面
header('Location: login.php?success=已成功退出登录');
exit;
?>

9. 运行项目

  1. 确保数据库已创建并创建了 users
  2. 启动本地服务器
  3. 访问 http://localhost/user-auth-system/index.php
  4. 点击注册按钮,创建新用户
  5. 使用注册的账号登录
  6. 查看个人资料
  7. 退出登录

10. 功能扩展

1. 添加密码重置功能

创建 forgot_password.php 文件:

php
<?php
// forgot_password.php
session_start();

// 如果已登录,跳转到首页
if (isset($_SESSION['user_id'])) {
    header('Location: index.php');
    exit;
}

$error = '';
$success = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['reset'])) {
    require_once 'db.php';
    $conn = getDbConnection();
    
    $email = $_POST['email'];
    
    if (empty($email)) {
        $error = '请输入邮箱';
    } else {
        // 检查邮箱是否存在
        $stmt = $conn->prepare("SELECT id, username FROM users WHERE email = ?");
        $stmt->bind_param("s", $email);
        $stmt->execute();
        $result = $stmt->get_result();
        
        if ($result->num_rows > 0) {
            // 生成重置密码链接
            $user = $result->fetch_assoc();
            $token = bin2hex(random_bytes(32));
            $expiry = date('Y-m-d H:i:s', time() + 3600); // 1小时有效期
            
            // 存储重置令牌(实际应用中应该存储在数据库)
            // 这里简化处理,直接在URL中传递
            $resetLink = "http://localhost/user-auth-system/reset_password.php?token=$token&email=$email";
            
            // 实际应用中应该发送邮件
            $success = "重置密码链接已发送到您的邮箱: $resetLink";
        } else {
            $error = '邮箱不存在';
        }
        
        $stmt->close();
    }
    
    $conn->close();
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>忘记密码</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <!-- 导航栏 -->
    <div class="navbar">
        <div class="container">
            <div class="logo">
                <h3>用户系统</h3>
            </div>
            <div class="nav-links">
                <a href="index.php">首页</a>
                <a href="login.php">登录</a>
                <a href="register.php">注册</a>
            </div>
        </div>
    </div>
    
    <div class="container">
        <h1>忘记密码</h1>
        
        <div class="form">
            <?php if (!empty($error)): ?>
                <div class="error"><?php echo $error; ?></div>
            <?php endif; ?>
            
            <?php if (!empty($success)): ?>
                <div class="success"><?php echo $success; ?></div>
            <?php endif; ?>
            
            <form action="" method="post">
                <div class="form-group">
                    <label>邮箱: <input type="email" name="email" required></label>
                </div>
                <button type="submit" name="reset">发送重置链接</button>
            </form>
            
            <div class="link">
                <a href="login.php">返回登录</a>
            </div>
        </div>
    </div>
</body>
</html>

创建 reset_password.php 文件:

php
<?php
// reset_password.php
session_start();

// 如果已登录,跳转到首页
if (isset($_SESSION['user_id'])) {
    header('Location: index.php');
    exit;
}

$error = '';
$success = '';

if (isset($_GET['token']) && isset($_GET['email'])) {
    $token = $_GET['token'];
    $email = $_GET['email'];
    
    // 实际应用中应该验证令牌
    
    if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update'])) {
        require_once 'db.php';
        $conn = getDbConnection();
        
        $password = $_POST['password'];
        $confirmPassword = $_POST['confirm_password'];
        
        if (empty($password) || empty($confirmPassword)) {
            $error = '所有字段都不能为空';
        } elseif ($password !== $confirmPassword) {
            $error = '两次输入的密码不一致';
        } elseif (strlen($password) < 6) {
            $error = '密码长度至少为6位';
        } else {
            // 密码加密
            $hashedPassword = password_hash($password, PASSWORD_DEFAULT);
            
            // 更新密码
            $stmt = $conn->prepare("UPDATE users SET password = ? WHERE email = ?");
            $stmt->bind_param("ss", $hashedPassword, $email);
            
            if ($stmt->execute()) {
                $success = '密码重置成功,请登录';
            } else {
                $error = '密码重置失败,请重试';
            }
            
            $stmt->close();
        }
        
        $conn->close();
    }
} else {
    header('Location: forgot_password.php?error=无效的重置链接');
    exit;
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>重置密码</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <!-- 导航栏 -->
    <div class="navbar">
        <div class="container">
            <div class="logo">
                <h3>用户系统</h3>
            </div>
            <div class="nav-links">
                <a href="index.php">首页</a>
                <a href="login.php">登录</a>
                <a href="register.php">注册</a>
            </div>
        </div>
    </div>
    
    <div class="container">
        <h1>重置密码</h1>
        
        <div class="form">
            <?php if (!empty($error)): ?>
                <div class="error"><?php echo $error; ?></div>
            <?php endif; ?>
            
            <?php if (!empty($success)): ?>
                <div class="success"><?php echo $success; ?></div>
                <div class="link">
                    <a href="login.php">立即登录</a>
                </div>
            <?php else: ?>
                <form action="" method="post">
                    <div class="form-group">
                        <label>新密码: <input type="password" name="password" required></label>
                    </div>
                    <div class="form-group">
                        <label>确认新密码: <input type="password" name="confirm_password" required></label>
                    </div>
                    <button type="submit" name="update">更新密码</button>
                </form>
            <?php endif; ?>
        </div>
    </div>
</body>
</html>

2. 添加用户信息编辑功能

修改 profile.php 文件,添加编辑功能:

php
<?php
// profile.php
session_start();

// 检查是否登录
if (!isset($_SESSION['user_id'])) {
    header('Location: login.php');
    exit;
}

require_once 'db.php';
$conn = getDbConnection();

$error = '';
$success = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update'])) {
    $email = $_POST['email'];
    
    if (empty($email)) {
        $error = '邮箱不能为空';
    } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $error = '邮箱格式不正确';
    } else {
        // 检查邮箱是否已被其他用户使用
        $stmt = $conn->prepare("SELECT id FROM users WHERE email = ? AND id != ?");
        $stmt->bind_param("si", $email, $_SESSION['user_id']);
        $stmt->execute();
        $result = $stmt->get_result();
        
        if ($result->num_rows > 0) {
            $error = '邮箱已被其他用户使用';
        } else {
            // 更新邮箱
            $stmt = $conn->prepare("UPDATE users SET email = ? WHERE id = ?");
            $stmt->bind_param("si", $email, $_SESSION['user_id']);
            
            if ($stmt->execute()) {
                $_SESSION['email'] = $email;
                $success = '个人资料更新成功';
            } else {
                $error = '更新失败,请重试';
            }
        }
        
        $stmt->close();
    }
}

$conn->close();
?>

<!DOCTYPE html>
<html>
<head>
    <title>个人资料</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <!-- 导航栏 -->
    <div class="navbar">
        <div class="container">
            <div class="logo">
                <h3>用户系统</h3>
            </div>
            <div class="nav-links">
                <a href="index.php">首页</a>
                <a href="logout.php">退出登录</a>
            </div>
        </div>
    </div>
    
    <div class="container">
        <h1>个人资料</h1>
        
        <div class="profile">
            <h2>欢迎,<?php echo $_SESSION['username']; ?></h2>
            
            <?php if (!empty($error)): ?>
                <div class="error"><?php echo $error; ?></div>
            <?php endif; ?>
            
            <?php if (!empty($success)): ?>
                <div class="success"><?php echo $success; ?></div>
            <?php endif; ?>
            
            <form action="" method="post">
                <div class="form-group">
                    <label>用户名: <input type="text" name="username" value="<?php echo $_SESSION['username']; ?>" disabled></label>
                </div>
                <div class="form-group">
                    <label>邮箱: <input type="email" name="email" value="<?php echo $_SESSION['email']; ?>" required></label>
                </div>
                <div class="form-group">
                    <label>用户ID: <input type="text" value="<?php echo $_SESSION['user_id']; ?>" disabled></label>
                </div>
                <button type="submit" name="update">更新资料</button>
            </form>
            
            <div class="link" style="margin-top: 30px;">
                <a href="logout.php">退出登录</a>
            </div>
        </div>
    </div>
</body>
</html>

11. 注意事项

  1. 安全性

    • 使用 password_hashpassword_verify 进行密码加密和验证
    • 使用预处理语句防止 SQL 注入
    • 验证用户输入
    • 使用会话管理用户状态
  2. 性能

    • 优化数据库查询
    • 合理使用会话
  3. 用户体验

    • 提供清晰的错误提示
    • 显示操作成功的反馈
    • 友好的界面设计
  4. 兼容性

    • 确保在不同浏览器中正常显示
    • 响应式设计,适配不同屏幕尺寸

练习

  1. 实现完整的用户注册登录系统
  2. 添加密码重置功能
  3. 添加用户信息编辑功能
  4. 优化用户界面和体验
  5. 添加更多安全措施,如验证码、登录尝试限制等

© 2026 编程马·菜鸟教程 版权所有