源码特点
- MVC思想:代码结构清晰,分为模型、视图、控制器。
- 安全第一:
- 使用 PDO 预处理语句,彻底防止 SQL注入。
- 对用户输出进行 HTML实体转义,防止 XSS攻击。
- 密码使用
password_hash()和password_verify()进行安全哈希验证,绝不存储明文密码。
- 会话管理:使用 PHP
$_SESSION安全地管理用户登录状态。 - 用户友好:清晰的错误提示和成功反馈。
- 完整流程:包含注册、登录、登出和受保护页面。
第一步:创建数据库
你需要一个 MySQL 数据库来存储用户信息,请执行以下 SQL 语句来创建 users 表。

(图片来源网络,侵删)
-- 创建一个名为 `my_webapp` 的数据库 (如果不存在)
CREATE DATABASE IF NOT EXISTS my_webapp;
-- 使用该数据库
USE my_webapp;
-- 创建 users 表
CREATE TABLE IF NOT EXISTS `users` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL UNIQUE,
`password` VARCHAR(255) NOT NULL,
`email` VARCHAR(100) NOT NULL UNIQUE,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 插入一个测试用户 (密码是 'password123')
-- 你可以使用在线工具生成 password_hash 的值,或者直接用下面的代码注册一个新用户
INSERT INTO `users` (`username`, `password`, `email`) VALUES
('admin', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'admin@example.com');
注意:password 字段长度设为 255,因为 password_hash() 生成的哈希值很长。
第二步:创建项目文件结构
在你的 Web 服务器根目录(htdocs 或 www)下,创建如下文件夹和文件:
/login-module/
├── config/
│ └── db.php # 数据库配置文件
├── models/
│ └── User.php # 用户模型,处理数据库交互
├── controllers/
│ ├── auth.php # 处理注册和登录逻辑
│ └── home.php # 处理首页逻辑
├── views/
│ ├── header.php # 公共头部
│ ├── footer.php # 公共尾部
│ ├── register.php # 注册页面
│ ├── login.php # 登录页面
│ └── dashboard.php # 登录后的受保护页面
├── index.php # 入口文件,处理路由
└── logout.php # 登出处理文件
第三步:编写源码代码
将以下代码复制到对应的文件中。
config/db.php - 数据库配置
<?php
// 数据库配置信息
define('DB_HOST', 'localhost');
define('DB_USER', 'root'); // 你的数据库用户名
define('DB_PASS', ''); // 你的数据库密码
define('DB_NAME', 'my_webapp'); // 你的数据库名
// 创建 PDO 实例
try {
$pdo = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4", DB_USER, DB_PASS);
// 设置 PDO 错误模式为异常
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
// 如果连接失败,停止脚本并显示错误信息
die("无法连接到数据库: " . $e->getMessage());
}
models/User.php - 用户模型
<?php
class User {
private $pdo;
public function __construct($pdo) {
$this->pdo = $pdo;
}
/**
* 注册新用户
* @param string $username 用户名
* @param string $password 密码
* @param string $email 邮箱
* @return bool|string 成功返回 true,失败返回错误信息
*/
public function register($username, $password, $email) {
// 检查用户名是否已存在
if ($this->usernameExists($username)) {
return "用户名已被使用。";
}
// 检查邮箱是否已存在
if ($this->emailExists($email)) {
return "邮箱已被注册。";
}
// 使用 password_hash() 哈希密码
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
try {
// 准备 SQL 语句
$stmt = $this->pdo->prepare("INSERT INTO users (username, password, email) VALUES (?, ?, ?)");
// 执行语句,绑定参数
$stmt->execute([$username, $hashedPassword, $email]);
return true; // 注册成功
} catch (PDOException $e) {
return "注册失败: " . $e->getMessage();
}
}
/**
* 验证用户登录
* @param string $username 用户名
* @param string $password 密码
* @return bool|string 成功返回用户数据,失败返回 false 或错误信息
*/
public function login($username, $password) {
try {
$stmt = $this->pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user && password_verify($password, $user['password'])) {
// 密码正确,返回用户数据
return $user;
} else {
// 用户名或密码错误
return false;
}
} catch (PDOException $e) {
return "登录错误: " . $e->getMessage();
}
}
/**
* 检查用户名是否存在
*/
private function usernameExists($username) {
$stmt = $this->pdo->prepare("SELECT id FROM users WHERE username = ?");
$stmt->execute([$username]);
return $stmt->fetch() !== false;
}
/**
* 检查邮箱是否存在
*/
private function emailExists($email) {
$stmt = $this->pdo->prepare("SELECT id FROM users WHERE email = ?");
$stmt->execute([$email]);
return $stmt->fetch() !== false;
}
}
controllers/auth.php - 认证控制器
<?php
require_once __DIR__ . '/../config/db.php';
require_once __DIR__ . '/../models/User.php';
// 初始化用户模型
$user = new User($pdo);
// 处理注册请求
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['register'])) {
$username = trim($_POST['username']);
$password = trim($_POST['password']);
$email = trim($_POST['email']);
$result = $user->register($username, $password, $email);
if ($result === true) {
header("Location: index.php?page=login&message=注册成功,请登录!");
exit;
} else {
$error = $result;
}
}
// 处理登录请求
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['login'])) {
$username = trim($_POST['username']);
$password = trim($_POST['password']);
$user_data = $user->login($username, $password);
if ($user_data !== false) {
// 登录成功,设置会话
session_start();
$_SESSION['user_id'] = $user_data['id'];
$_SESSION['username'] = $user_data['username'];
header("Location: index.php?page=dashboard");
exit;
} else {
$error = "用户名或密码错误。";
}
}
controllers/home.php - 首页控制器
<?php
// 首页逻辑很简单,可以在这里添加一些欢迎信息或重定向逻辑
// 如果用户已登录,直接跳转到仪表盘
session_start();
if (isset($_SESSION['user_id'])) {
header("Location: index.php?page=dashboard");
exit;
}
views/header.php - 公共头部
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">登录模块</title>
<style>
body { font-family: Arial, sans-serif; background-color: #f4f4f4; margin: 0; padding: 20px; }
.container { max-width: 500px; margin: auto; background: white; padding: 20px; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.1); }
h2 { text-align: center; }
.form-group { margin-bottom: 15px; }
label { display: block; margin-bottom: 5px; }
input[type="text"], input[type="password"], input[type="email"] { width: 100%; padding: 8px; box-sizing: border-box; border: 1px solid #ddd; border-radius: 4px; }
input[type="submit"] { background-color: #5cb85c; color: white; padding: 10px 15px; border: none; border-radius: 4px; cursor: pointer; width: 100%; }
input[type="submit"]:hover { background-color: #4cae4c; }
.error { color: #d9534f; background-color: #f9f2f2; padding: 10px; border-radius: 4px; margin-bottom: 15px; }
.success { color: #5cb85c; background-color: #dff0d8; padding: 10px; border-radius: 4px; margin-bottom: 15px; }
.nav { margin-bottom: 20px; text-align: center; }
.nav a { margin: 0 10px; text-decoration: none; color: #007bff; }
</style>
</head>
<body>
<div class="container">
<div class="nav">
<a href="index.php">首页</a>
<a href="index.php?page=register">注册</a>
<a href="index.php?page=login">登录</a>
</div>
views/footer.php - 公共尾部
</div> </body> </html>
views/register.php - 注册页面视图
<?php require 'header.php'; ?>
<h2>用户注册</h2>
<?php if (isset($error)): ?>
<p class="error"><?php echo htmlspecialchars($error); ?></p>
<?php endif; ?>
<form action="index.php?page=register" method="post">
<div class="form-group">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required>
</div>
<div class="form-group">
<label for="email">邮箱:</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="password">密码:</label>
<input type="password" id="password" name="password" required>
</div>
<div class="form-group">
<input type="submit" name="register" value="注册">
</div>
</form>
<?php require 'footer.php'; ?>
views/login.php - 登录页面视图
<?php require 'header.php'; ?>
<h2>用户登录</h2>
<?php if (isset($error)): ?>
<p class="error"><?php echo htmlspecialchars($error); ?></p>
<?php endif; ?>
<?php if (isset($_GET['message'])): ?>
<p class="success"><?php echo htmlspecialchars($_GET['message']); ?></p>
<?php endif; ?>
<form action="index.php?page=login" method="post">
<div class="form-group">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required>
</div>
<div class="form-group">
<label for="password">密码:</label>
<input type="password" id="password" name="password" required>
</div>
<div class="form-group">
<input type="submit" name="login" value="登录">
</div>
</form>
<?php require 'footer.php'; ?>
views/dashboard.php - 受保护页面(仪表盘)
<?php require 'header.php'; ?> <h2>欢迎, <?php echo htmlspecialchars($_SESSION['username']); ?>!</h2> <p>这是一个受保护的页面,只有登录用户才能看到。</p> <p><a href="logout.php">安全登出</a></p> <?php require 'footer.php'; ?>
index.php - 入口文件(路由)
<?php
// 开启会话,以便在整个应用中使用
session_start();
// 定义页面参数
$page = isset($_GET['page']) ? $_GET['page'] : 'home';
// 根据页面参数加载对应的控制器
switch ($page) {
case 'register':
require_once 'controllers/auth.php';
require_once 'views/register.php';
break;
case 'login':
require_once 'controllers/auth.php';
require_once 'views/login.php';
break;
case 'dashboard':
// 检查用户是否已登录
if (!isset($_SESSION['user_id'])) {
header("Location: index.php?page=login");
exit;
}
require_once 'controllers/home.php';
require_once 'views/dashboard.php';
break;
case 'home':
default:
require_once 'controllers/home.php';
// 默认显示首页内容,可以在这里放一些公开信息
// 或者直接重定向到登录/注册页
require_once 'views/header.php';
echo "<h2>欢迎使用登录系统</h2>";
echo "<p>请 <a href='index.php?page=login'>登录</a> 或 <a href='index.php?page=register'>注册</a>。</p>";
require_once 'views/footer.php';
break;
}
logout.php - 登出处理
<?php
// 开启会话
session_start();
// 清空所有会话变量
$_SESSION = array();
// 如果要完全销毁会话,也销毁会话 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"]
);
}
// 销毁会话
session_destroy();
// 重定向到登录页面
header("Location: index.php?page=login");
exit;
第四步:如何运行
- Web 环境:确保你有一个支持 PHP 的 Web 服务器,如 Apache 或 Nginx,如果你是本地开发,可以使用 XAMPP、WAMP 或 MAMP。
- 数据库配置:修改
config/db.php文件中的数据库用户名、密码和数据库名,使其与你的实际配置一致。 - 放置文件:将整个
login-module文件夹复制到你的 Web 服务器的根目录下。 - 访问:在浏览器中访问
http://localhost/login-module/。- 你会看到首页,有链接可以跳转到注册和登录页面。
- 你可以注册一个新用户。
- 用新注册的用户或默认的
admin/password123登录。 - 登录成功后,你会被带到
dashboard.php页面。 - 如果未登录,直接访问
dashboard.php会被自动重定向到登录页面。
总结与扩展
这份源码是一个很好的起点,你可以基于此进行扩展,

(图片来源网络,侵删)
- 添加“记住我”功能:使用
setcookie()和额外的数据库字段来实现。 - 密码重置功能:通过发送包含令牌的邮件来实现。
- 用户个人资料编辑:增加修改用户名、邮箱、密码的功能。
- 使用 Composer:引入更现代的依赖管理,比如使用
illuminate/database(Laravel 的 Eloquent ORM) 替代原生 PDO。 - 前端框架:使用 Bootstrap、Vue.js 或 React 来美化界面和提升用户体验。
