本文目录导读:

我来详细说明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());
}
?>
安全最佳实践
- 密码存储:使用
password_hash()和password_verify() - 输入验证:始终验证和清理用户输入
- 输出编码:使用
htmlspecialchars()防止XSS - SQL注入防护:使用预处理语句(PDO)
- Session安全:设置
session.cookie_httponly和session.cookie_secure - CSRF防护:在表单中添加token验证
- HTTPS:生产环境必须使用HTTPS
- 登录限制:限制登录尝试次数防止暴力破解
这是一个完整的用户登录系统实现,包含了注册、登录、会话管理、"记住我"功能和退出功能,根据项目需求,你可以添加验证码、邮箱验证、密码重置等功能来增强安全性。