核心功能特点
- 用户注册:用户可以填写用户名、密码、邮箱进行注册。
- 密码安全:使用 PHP 内置的
password_hash()和password_verify()函数进行密码的哈希加密和验证,这是目前最推荐的安全做法。 - 用户登录:已注册用户可以凭用户名和密码登录。
- 会话管理:登录成功后,使用 PHP Session 来保持用户的登录状态。
- 登出功能:用户可以安全地退出登录,并清除 Session。
- 防止重复注册:在注册时会检查用户名和邮箱是否已被使用。
- 防止 SQL 注入:使用 预处理语句 来与数据库交互,这是防止 SQL 注入攻击的最佳实践。
项目结构
为了保持代码清晰,我们采用一个简单的项目结构:

(图片来源网络,侵删)
/user_auth_system/
├── config.php # 数据库配置文件
├── create_tables.sql # 创建数据库和表的 SQL 文件
├── register.php # 注册页面和逻辑
├── login.php # 登录页面和逻辑
├── logout.php # 登出逻辑
├── dashboard.php # 登录后才能访问的受保护页面
├── style.css # 基础样式文件
└── index.html # 项目首页,提供注册和登录入口
第一步:环境准备
在运行代码之前,请确保您的电脑上已经安装了以下软件:
- Web 服务器:如 Apache 或 Nginx。
- PHP:版本建议 7.4 或更高。
- MySQL:数据库服务器。
- 集成环境:如果您不想单独安装,可以使用集成的开发环境,如 XAMPP、WAMP (Windows)、MAMP (Mac) 或 LAMP (Linux),这些环境已经包含了上述所有软件。
第二步:创建数据库和表
- 启动您的 MySQL 服务(通过 XAMPP/WAMP 等控制面板)。
- 打开 phpMyAdmin(通常在
http://localhost/phpmyadmin/)。 - 创建一个新的数据库,例如命名为
user_auth_db。 - 点击“导入”或“SQL”,然后将下面的 SQL 代码粘贴进去并执行。
create_tables.sql 文件内容:
-- 创建用户表
CREATE TABLE `users` (
`id` INT(11) NOT NULL 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,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 插入一条测试数据 (密码是 'password123')
-- INSERT INTO `users` (`username`, `email`, `password`) VALUES ('admin', 'admin@example.com', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi');
第三步:下载和配置代码
您可以直接将以下所有代码文件复制到您的 Web 服务器的根目录(XAMPP 的 htdocs 文件夹)下的一个新文件夹中,user_auth_system。
数据库配置 (config.php)
这个文件用于连接您的数据库。请务必修改其中的用户名、密码和数据库名。

(图片来源网络,侵删)
<?php
// 数据库连接配置
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'root'); // 您的数据库用户名
define('DB_PASSWORD', ''); // 您的数据库密码
define('DB_NAME', 'user_auth_db'); // 您的数据库名
// 尝试连接到 MySQL 数据库
$link = mysqli_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);
// 检查连接是否成功
if($link === false){
die("ERROR: Could not connect. " . mysqli_connect_error());
}
?>
注册页面 (register.php)
这个文件包含了一个 HTML 表单用于用户输入,以及 PHP 代码来处理注册逻辑。
<?php
// 包含数据库配置文件
require_once "config.php";
// 定义变量并初始化为空
$username = $email = $password = $confirm_password = "";
$username_err = $email_err = $password_err = $confirm_password_err = "";
$registration_success = "";
// 处理表单数据
if($_SERVER["REQUEST_METHOD"] == "POST"){
// 验证用户名
if(empty(trim($_POST["username"]))){
$username_err = "请输入用户名。";
} else {
// 准备一个 select 语句
$sql = "SELECT id FROM users WHERE username = ?";
if($stmt = mysqli_prepare($link, $sql)){
// 绑定变量作为参数
mysqli_stmt_bind_param($stmt, "s", $param_username);
// 设置参数
$param_username = trim($_POST["username"]);
// 尝试执行预处理语句
if(mysqli_stmt_execute($stmt)){
/* 存储结果 */
mysqli_stmt_store_result($stmt);
if(mysqli_stmt_num_rows($stmt) == 1){
$username_err = "该用户名已被使用。";
} else{
$username = trim($_POST["username"]);
}
} else{
echo "出错了! 请稍后再试。";
}
// 关闭语句
mysqli_stmt_close($stmt);
}
}
// 验证邮箱
if(empty(trim($_POST["email"]))){
$email_err = "请输入邮箱。";
} else {
// 准备一个 select 语句
$sql = "SELECT id FROM users WHERE email = ?";
if($stmt = mysqli_prepare($link, $sql)){
mysqli_stmt_bind_param($stmt, "s", $param_email);
$param_email = trim($_POST["email"]);
if(mysqli_stmt_execute($stmt)){
mysqli_stmt_store_result($stmt);
if(mysqli_stmt_num_rows($stmt) == 1){
$email_err = "该邮箱已被注册。";
} else{
$email = trim($_POST["email"]);
}
} else{
echo "出错了! 请稍后再试。";
}
mysqli_stmt_close($stmt);
}
}
// 验证密码
if(empty(trim($_POST["password"]))){
$password_err = "请输入密码。";
} elseif(strlen(trim($_POST["password"])) < 6){
$password_err = "密码至少需要6个字符。";
} else{
$password = trim($_POST["password"]);
}
// 验证确认密码
if(empty(trim($_POST["confirm_password"]))){
$confirm_password_err = "请确认密码。";
} else{
$confirm_password = trim($_POST["confirm_password"]);
if(empty($password_err) && ($password != $confirm_password)){
$confirm_password_err = "两次输入的密码不匹配。";
}
}
// 检查输入错误是否为空
if(empty($username_err) && empty($email_err) && empty($password_err) && empty($confirm_password_err)){
// 准备插入语句
$sql = "INSERT INTO users (username, email, password) VALUES (?, ?, ?)";
if($stmt = mysqli_prepare($link, $sql)){
// 绑定变量
mysqli_stmt_bind_param($stmt, "sss", $param_username, $param_email, $param_password);
// 设置参数
$param_username = $username;
$param_email = $email;
// 使用 password_hash() 加密密码
$param_password = password_hash($password, PASSWORD_DEFAULT);
// 尝试执行预处理语句
if(mysqli_stmt_execute($stmt)){
$registration_success = "注册成功! <a href='login.php'>请点击登录</a>";
} else{
echo "出错了! 请稍后再试。";
}
// 关闭语句
mysqli_stmt_close($stmt);
}
}
// 关闭连接
mysqli_close($link);
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">注册</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="wrapper">
<h2>创建新账户</h2>
<p>请填写此表单以创建账户。</p>
<?php
if(!empty($registration_success)){
echo '<div class="alert-success">' . $registration_success . '</div>';
}
?>
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post">
<div class="form-group">
<label>用户名</label>
<input type="text" name="username" value="<?php echo $username; ?>">
<span class="error"><?php echo $username_err; ?></span>
</div>
<div class="form-group">
<label>邮箱</label>
<input type="email" name="email" value="<?php echo $email; ?>">
<span class="error"><?php echo $email_err; ?></span>
</div>
<div class="form-group">
<label>密码</label>
<input type="password" name="password">
<span class="error"><?php echo $password_err; ?></span>
</div>
<div class="form-group">
<label>确认密码</label>
<input type="password" name="confirm_password">
<span class="error"><?php echo $confirm_password_err; ?></span>
</div>
<div class="form-group">
<input type="submit" class="btn" value="提交">
</div>
<p>已有账户? <a href="login.php">请登录</a>.</p>
</form>
</div>
</body>
</html>
登录页面 (login.php)
这个文件处理用户的登录验证。
<?php
// 初始化 session
session_start();
// 检查用户是否已经登录,如果是则跳转到仪表盘
if(isset($_SESSION["loggedin"]) && $_SESSION["loggedin"] === true){
header("location: dashboard.php");
exit;
}
// 包含数据库配置文件
require_once "config.php";
// 定义变量并初始化为空
$username = $password = "";
$username_err = $password_err = $login_err = "";
// 处理表单数据
if($_SERVER["REQUEST_METHOD"] == "POST"){
// 验证用户名是否为空
if(empty(trim($_POST["username"]))){
$username_err = "请输入用户名。";
} else{
$username = trim($_POST["username"]);
}
// 验证密码是否为空
if(empty(trim($_POST["password"]))){
$password_err = "请输入密码。";
} else{
$password = trim($_POST["password"]);
}
// 验证凭据
if(empty($username_err) && empty($password_err)){
// 准备一个 select 语句
$sql = "SELECT id, username, password FROM users WHERE username = ?";
if($stmt = mysqli_prepare($link, $sql)){
// 绑定变量
mysqli_stmt_bind_param($stmt, "s", $param_username);
// 设置参数
$param_username = $username;
// 尝试执行预处理语句
if(mysqli_stmt_execute($stmt)){
// 存储结果
mysqli_stmt_store_result($stmt);
if(mysqli_stmt_num_rows($stmt) == 1){
// 绑定结果变量
mysqli_stmt_bind_result($stmt, $id, $username, $hashed_password);
if(mysqli_stmt_fetch($stmt)){
// 验证密码
if(password_verify($password, $hashed_password)){
// 密码正确,开始一个新的 session
session_start();
// 在 session 中存储数据
$_SESSION["loggedin"] = true;
$_SESSION["id"] = $id;
$_SESSION["username"] = $username;
// 跳转到仪表盘
header("location: dashboard.php");
} else{
// 密码不正确
$login_err = "用户名或密码不正确。";
}
}
} else{
// 用户名不存在
$login_err = "用户名或密码不正确。";
}
} else{
echo "出错了! 请稍后再试。";
}
// 关闭语句
mysqli_stmt_close($stmt);
}
}
// 关闭连接
mysqli_close($link);
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">登录</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="wrapper">
<h2>登录</h2>
<p>请填写您的用户名和密码进行登录。</p>
<?php
if(!empty($login_err)){
echo '<div class="alert-error">' . $login_err . '</div>';
}
?>
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post">
<div class="form-group">
<label>用户名</label>
<input type="text" name="username" value="<?php echo $username; ?>">
<span class="error"><?php echo $username_err; ?></span>
</div>
<div class="form-group">
<label>密码</label>
<input type="password" name="password">
<span class="error"><?php echo $password_err; ?></span>
</div>
<div class="form-group">
<input type="submit" class="btn" value="登录">
</div>
<p>还没有账户? <a href="register.php">请注册</a>.</p>
</form>
</div>
</body>
</html>
登出逻辑 (logout.php)
这个文件很简单,用于销毁 Session 并将用户重定向到登录页面。
<?php
// 初始化 session
session_start();
// 销毁 session 变量
$_SESSION = array();
// 销毁 session
session_destroy();
// 重定向到登录页面
header("location: login.php");
exit;
?>
受保护页面 (dashboard.php)
这个页面只有登录用户才能访问,它会检查 Session 中的 loggedin 变量。
<?php
// 初始化 session
session_start();
// 检查用户是否已登录,如果未登录则重定向到登录页面
if(!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true){
header("location: login.php");
exit;
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">仪表盘</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="wrapper">
<h1>欢迎, <b><?php echo htmlspecialchars($_SESSION["username"]); ?></b>!</h1>
<p>
<a href="logout.php" class="btn btn-danger">登出</a>
</p>
</div>
</body>
</html>
样式文件 (style.css)
为了让页面看起来更美观,添加一些简单的 CSS 样式。
body { font: 16px sans-serif; background-color: #f7f7f7; }
.wrapper { width: 400px; padding: 20px; margin: 50px auto; background-color: #fff; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.1); }
.wrapper h2 { text-align: center; }
.form-group { margin-bottom: 15px; }
.form-group label { display: block; margin-bottom: 5px; }
.form-group input[type="text"],
.form-group input[type="password"],
.form-group input[type="email"] {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box; /* Important for padding and width */
}
.btn { display: inline-block; background-color: #4CAF50; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; text-decoration: none; font-size: 16px; }
.btn:hover { background-color: #45a049; }
.btn-danger { background-color: #f44336; }
.btn-danger:hover { background-color: #d32f2f; }
.error { color: #f44336; font-size: 0.9em; display: block; margin-top: 5px; }
.alert-error { padding: 15px; margin-bottom: 20px; border: 1px solid transparent; border-radius: 4px; color: #a94442; background-color: #f2dede; border-color: #ebccd1; }
.alert-success { padding: 15px; margin-bottom: 20px; border: 1px solid transparent; border-radius: 4px; color: #3c763d; background-color: #dff0d8; border-color: #d6e9c6; }
项目首页 (index.html)
一个简单的首页,方便用户进入注册或登录。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">用户认证系统</title>
<link rel="stylesheet" href="style.css">
<style>
.home-wrapper { text-align: center; margin-top: 100px; }
.home-wrapper h1 { color: #333; }
.home-wrapper p { font-size: 1.2em; margin: 20px 0; }
.home-wrapper a { margin: 0 10px; }
</style>
</head>
<body>
<div class="home-wrapper">
<h1>欢迎使用用户认证系统</h1>
<p>
<a href="register.php" class="btn">注册新账户</a>
<a href="login.php" class="btn">登录已有账户</a>
</p>
</div>
</body>
</html>
如何运行
- 将所有上述文件放入您的 Web 服务器根目录(如
htdocs/user_auth_system)。 - 确保
create_tables.sql中的数据库名称与config.php中的一致。 - 确保 MySQL 服务正在运行。
- 在浏览器中访问
http://localhost/user_auth_system/(根据您的服务器和路径调整)。 - 您就可以看到首页,然后点击链接进行注册和登录测试了。
进阶学习建议
这个示例是一个基础框架,在实际项目中,您可能还需要考虑:
- 验证码:防止机器人恶意注册和登录。
- 邮件验证:用户注册后,发送一封带有验证链接的邮件到其邮箱,点击后才能激活账户。
- “记住我”功能:使用长期 Cookie 实现自动登录。
- 密码重置功能:通过邮件发送一个重置密码的链接。
- 更完善的错误处理和日志记录。
- 使用 PDO (PHP Data Objects):PDO 是另一种数据库抽象层,功能更强大,跨数据库性更好。
- 使用 MVC 框架:对于大型项目,使用如 Laravel、Symfony 等现代 PHP 框架可以极大地提高开发效率和代码质量。
