Appearance
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. 运行项目
- 确保数据库已创建并创建了
users表 - 启动本地服务器
- 访问
http://localhost/user-auth-system/index.php - 点击注册按钮,创建新用户
- 使用注册的账号登录
- 查看个人资料
- 退出登录
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. 注意事项
安全性:
- 使用
password_hash和password_verify进行密码加密和验证 - 使用预处理语句防止 SQL 注入
- 验证用户输入
- 使用会话管理用户状态
- 使用
性能:
- 优化数据库查询
- 合理使用会话
用户体验:
- 提供清晰的错误提示
- 显示操作成功的反馈
- 友好的界面设计
兼容性:
- 确保在不同浏览器中正常显示
- 响应式设计,适配不同屏幕尺寸
练习
- 实现完整的用户注册登录系统
- 添加密码重置功能
- 添加用户信息编辑功能
- 优化用户界面和体验
- 添加更多安全措施,如验证码、登录尝试限制等
