1. 系统概述
用户登录系统是Web应用的基础功能之一。本教程将指导您创建一个安全可靠的PHP登录系统,包含以下功能:
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应用提供坚实的基础。记得根据实际需求调整和扩展这些功能,并始终保持对安全问题的关注。

