尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

PHP+MySQL员工管理系统实战:从环境搭建到安全部署完整教程

PHP+MySQL员工管理系统实战:从环境搭建到安全部署完整教程
📅 发布时间:2026/7/25 8:52:08

最近在帮朋友公司搭建一个简单的内部员工管理系统,从需求分析到上线部署走了一遍完整流程。这类系统在企业日常运营中非常实用,但网上很多教程要么过于简单只贴代码,要么过于复杂引入了不必要的框架。本文将分享一套基于 PHP + MySQL 的轻量级员工管理系统实战开发教程,从环境搭建、数据库设计、前后端编码到安全优化,手把手带你构建一个功能完整、代码清晰、可直接用于课程设计或小型团队管理的系统。无论你是 PHP 初学者想练手,还是需要快速搭建一个内部管理工具,都能从本文中找到可复用的代码和思路。

1. 系统概述与核心功能设计

在开始编码之前,明确系统要做什么至关重要。一个基础的员工管理系统,核心是围绕“人”的信息进行增删改查(CRUD)管理,并区分不同角色的操作权限。

1.1 系统角色与功能模块

根据常见的业务场景,我们将系统用户分为两类角色:

  1. 管理员:拥有系统的最高权限,负责管理整个系统的数据和用户。
  2. 普通员工:只能查看和修改自己的相关信息。

对应的功能模块拆分如下:

管理员端功能:

  • 员工信息管理:添加新员工、查看所有员工列表、编辑员工信息、删除离职员工。
  • 部门管理:创建、编辑、删除部门,并将员工分配至相应部门。
  • 薪资信息管理:录入、修改、查看员工的薪资记录。
  • 系统用户管理:管理所有员工的登录账号和权限。

员工端功能:

  • 个人信息查看与编辑:查看个人资料,并可修改部分非核心信息(如联系电话、住址)。
  • 个人薪资查询:查看自己的历史薪资单。

1.2 技术栈选型与优势

  • 后端语言:PHP:语法简单易学,内置函数丰富,非常适合快速开发Web应用,且有庞大的社区支持。
  • 数据库:MySQL:开源、流行、与PHP搭配成熟(常被称为“黄金组合”),足以应对中小型系统的数据存储需求。
  • 前端技术:HTML, CSS, JavaScript (少量):用于构建用户界面。为了保持简洁,我们主要使用原生技术,并引入 Bootstrap 5 框架来快速美化界面。
  • 服务器:Apache / Nginx:本文演示环境使用 Apache。

选择这套技术栈的原因在于其学习曲线平缓、环境搭建简单,能让开发者更专注于业务逻辑的实现,而非复杂的配置。

2. 开发环境准备

工欲善其事,必先利其器。一个统一的开发环境能避免很多后续的兼容性问题。

2.1 集成环境安装

对于新手,强烈推荐使用集成环境包,它一次性安装了PHP、MySQL、Web服务器和必要的工具。这里推荐两款:

  1. XAMPP:适用于 Windows, macOS, Linux。包含 Apache, MySQL, PHP 和 Perl。
  2. phpStudy:国内开发者常用的集成环境,对中文支持友好,切换PHP版本方便。

以 XAMPP 为例的安装步骤:

  1. 访问 Apache Friends 官网下载对应操作系统的 XAMPP 安装包。
  2. 运行安装程序,建议安装路径不要包含中文和空格(如C:\xampp)。
  3. 安装完成后,启动 XAMPP 控制面板,点击Start按钮启动Apache和MySQL服务。当旁边的状态灯变为绿色,表示服务已成功运行。

2.2 检查环境与创建项目目录

  1. 测试PHP环境:在浏览器中访问http://localhost,如果看到 XAMPP 的欢迎页面,说明 Apache 运行正常。在 XAMPP 的安装目录下,找到htdocs文件夹(这是网站的根目录)。
  2. 创建项目文件夹:在htdocs文件夹内,新建一个文件夹,命名为employee_management。我们所有的项目文件都将放在这里。
  3. 测试MySQL:在浏览器中访问http://localhost/phpmyadmin,使用用户名root(XAMPP 默认密码为空)登录。能成功进入 phpMyAdmin 管理界面,说明 MySQL 服务正常。

2.3 代码编辑器选择

你可以使用任何熟悉的文本编辑器,如 VS Code、Sublime Text、PHPStorm 等。VS Code 配合 PHP 插件能提供很好的代码高亮和提示。

3. 数据库设计与实现

数据库是系统的基石,良好的设计是项目成功的关键。

3.1 数据库概念设计 (ER图)

我们至少需要四张核心表:

  1. departments:部门表
  2. employees:员工基本信息表
  3. salaries:薪资记录表
  4. users:系统用户表(用于登录认证)

表之间的关系:一个部门有多个员工(一对多),一个员工有多条薪资记录(一对多),一个员工对应一个系统用户(一对一)。

3.2 数据表结构SQL

打开 phpMyAdmin (http://localhost/phpmyadmin),新建一个数据库,命名为company_db,排序规则选择utf8mb4_general_ci。然后执行以下 SQL 语句创建表。

-- 创建部门表 CREATE TABLE `departments` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) NOT NULL COMMENT '部门名称', `description` text COMMENT '部门描述', `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='部门信息表'; -- 创建员工基本信息表 CREATE TABLE `employees` ( `id` int(11) NOT NULL AUTO_INCREMENT, `employee_id` varchar(20) NOT NULL COMMENT '员工工号', `name` varchar(50) NOT NULL COMMENT '姓名', `gender` enum('男','女','其他') DEFAULT NULL COMMENT '性别', `email` varchar(100) NOT NULL COMMENT '邮箱', `phone` varchar(20) DEFAULT NULL COMMENT '电话', `address` text COMMENT '住址', `department_id` int(11) DEFAULT NULL COMMENT '所属部门ID', `position` varchar(100) DEFAULT NULL COMMENT '职位', `hire_date` date NOT NULL COMMENT '入职日期', `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `employee_id` (`employee_id`), UNIQUE KEY `email` (`email`), KEY `department_id` (`department_id`), CONSTRAINT `employees_ibfk_1` FOREIGN KEY (`department_id`) REFERENCES `departments` (`id`) ON DELETE SET NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='员工基本信息表'; -- 创建系统用户表(与登录相关) CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `employee_id` varchar(20) NOT NULL COMMENT '关联的员工工号', `username` varchar(50) NOT NULL COMMENT '登录用户名', `password_hash` varchar(255) NOT NULL COMMENT '加密后的密码', `role` enum('admin','employee') NOT NULL DEFAULT 'employee' COMMENT '角色:admin-管理员, employee-普通员工', `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`), UNIQUE KEY `employee_id` (`employee_id`), CONSTRAINT `users_ibfk_1` FOREIGN KEY (`employee_id`) REFERENCES `employees` (`employee_id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统用户表'; -- 创建薪资记录表 CREATE TABLE `salaries` ( `id` int(11) NOT NULL AUTO_INCREMENT, `employee_id` varchar(20) NOT NULL COMMENT '员工工号', `base_salary` decimal(10,2) NOT NULL COMMENT '基本工资', `bonus` decimal(10,2) DEFAULT '0.00' COMMENT '奖金', `deductions` decimal(10,2) DEFAULT '0.00' COMMENT '扣款', `payment_date` date NOT NULL COMMENT '发薪月份(通常为月初)', `notes` text COMMENT '备注', `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `employee_id` (`employee_id`), CONSTRAINT `salaries_ibfk_1` FOREIGN KEY (`employee_id`) REFERENCES `employees` (`employee_id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='员工薪资记录表';

关键字段说明与设计思路:

  • 使用employee_id作为关联键:employees表的主键是自增id,但我们同时创建了业务上唯一的employee_id(工号)。users和salaries表通过employee_id与employees关联,这样即使员工内部ID变化,业务关联也不会断裂。
  • 密码存储:users表中的password_hash字段用于存储加密后的密码,绝对禁止明文存储。我们将使用 PHP 的password_hash()函数。
  • 外键约束:使用了FOREIGN KEY和ON DELETE CASCADE/SET NULL来保证数据完整性。例如,删除一个员工,其对应的登录用户和薪资记录也会自动删除。
  • 字符集:使用utf8mb4以支持存储 Emoji 等所有 Unicode 字符。

4. 项目结构搭建与公共组件

清晰的目录结构能让代码更易维护。

4.1 项目目录结构

在htdocs/employee_management文件夹内,创建如下目录和文件:

employee_management/ ├── assets/ # 静态资源 │ ├── css/ │ │ └── style.css │ └── js/ │ └── script.js ├── config/ # 配置文件 │ └── database.php ├── includes/ # 公共包含文件 │ ├── header.php │ ├── footer.php │ ├── auth.php # 认证相关函数 │ └── functions.php # 通用函数 ├── admin/ # 管理员后台页面 │ ├── index.php │ ├── employees.php │ ├── departments.php │ └── salaries.php ├── employee/ # 员工前端页面 │ ├── index.php │ ├── profile.php │ └── my_salary.php ├── index.php # 网站首页/登录页 ├── login.php # 登录处理 ├── logout.php # 退出登录 └── dashboard.php # 登录后根据角色跳转的仪表板

4.2 数据库连接配置

创建config/database.php,这是整个系统连接数据库的入口。

<?php // config/database.php session_start(); // 在需要会话的页面包含此文件 define('DB_SERVER', 'localhost'); define('DB_USERNAME', 'root'); define('DB_PASSWORD', ''); // XAMPP默认密码为空 define('DB_NAME', 'company_db'); // 创建数据库连接 $link = mysqli_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME); // 检查连接 if($link === false){ die("错误:无法连接到数据库。 " . mysqli_connect_error()); } // 设置字符集为 utf8mb4 mysqli_set_charset($link, "utf8mb4"); ?>

安全提醒:在生产环境中,务必使用强密码,并将数据库配置信息放在 Web 根目录之外,通过include引入。

4.3 页面公共头部与尾部

创建includes/header.php和includes/footer.php以实现页面布局统一。

<!-- includes/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>员工管理系统 - <?php echo $page_title ?? '主页'; ?></title> <!-- Bootstrap 5 CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> <!-- 自定义CSS --> <link href="/employee_management/assets/css/style.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-expand-lg navbar-dark bg-primary"> <div class="container-fluid"> <a class="navbar-brand" href="/employee_management/index.php">员工管理系统</a> <button class="navbar-toggler" type="button"><!-- includes/footer.php --> </div> <!-- 关闭 container div --> <!-- Bootstrap 5 JS Bundle --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script> <!-- 自定义JS --> <script src="/employee_management/assets/js/script.js"></script> </body> </html>

4.4 用户认证与权限检查

创建includes/auth.php,包含登录状态检查和权限验证函数。

<?php // includes/auth.php function isLoggedIn() { return isset($_SESSION['loggedin']) && $_SESSION['loggedin'] === true; } function requireLogin() { if (!isLoggedIn()) { header("location: /employee_management/index.php"); exit; } } function requireAdmin() { requireLogin(); if ($_SESSION['role'] !== 'admin') { // 非管理员,重定向到员工仪表板或显示错误 header("location: /employee_management/employee/index.php"); exit; } } function requireEmployee() { requireLogin(); // 此函数确保用户已登录,角色可以是 admin 或 employee } ?>

5. 核心功能模块实现

接下来,我们实现系统的几个核心页面。

5.1 用户登录与会话管理

登录页面 (index.php):

<?php // index.php $page_title = "用户登录"; include('includes/header.php'); // 如果用户已登录,直接跳转到仪表板 if(isset($_SESSION['loggedin']) && $_SESSION['loggedin'] === true){ header("location: dashboard.php"); exit; } ?> <div class="row justify-content-center"> <div class="col-md-6"> <div class="card"> <div class="card-header"> <h4 class="mb-0">用户登录</h4> </div> <div class="card-body"> <?php // 显示错误信息(来自 login.php) if(isset($_SESSION['error'])){ echo '<div class="alert alert-danger">' . $_SESSION['error'] . '</div>'; unset($_SESSION['error']); } ?> <form action="login.php" method="post"> <div class="mb-3"> <label for="username" class="form-label">用户名</label> <input type="text" class="form-control" id="username" name="username" required> </div> <div class="mb-3"> <label for="password" class="form-label">密码</label> <input type="password" class="form-control" id="password" name="password" required> </div> <button type="submit" class="btn btn-primary w-100">登录</button> </form> <p class="mt-3 text-center text-muted">默认管理员账号:admin / 密码:123456</p> </div> </div> </div> </div> <?php include('includes/footer.php'); ?>

登录处理 (login.php):

<?php // login.php session_start(); require_once('config/database.php'); if($_SERVER["REQUEST_METHOD"] == "POST"){ $username = trim($_POST['username']); $password = $_POST['password']; // 参数校验 if(empty($username) || empty($password)){ $_SESSION['error'] = "用户名和密码不能为空。"; header("location: index.php"); exit; } // 准备SQL,防止SQL注入 $sql = "SELECT u.id, u.username, u.password_hash, u.role, u.employee_id, e.name as employee_name FROM users u LEFT JOIN employees e ON u.employee_id = e.employee_id WHERE u.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, $role, $employee_id, $employee_name); if(mysqli_stmt_fetch($stmt)){ // 验证密码 if(password_verify($password, $hashed_password)){ // 密码正确,创建会话 $_SESSION['loggedin'] = true; $_SESSION['id'] = $id; $_SESSION['username'] = $username; $_SESSION['role'] = $role; $_SESSION['employee_id'] = $employee_id; $_SESSION['employee_name'] = $employee_name; // 重定向到仪表板 header("location: dashboard.php"); } else { $_SESSION['error'] = "密码错误。"; header("location: index.php"); } } } else { $_SESSION['error'] = "用户名不存在。"; header("location: index.php"); } } else { echo "糟糕!出错了,请稍后再试。"; } mysqli_stmt_close($stmt); } mysqli_close($link); } ?>

仪表板与路由 (dashboard.php):

<?php // dashboard.php session_start(); require_once('includes/auth.php'); requireLogin(); // 根据角色跳转到不同的主页 if ($_SESSION['role'] == 'admin') { header("location: admin/index.php"); } else { header("location: employee/index.php"); } exit; ?>

退出登录 (logout.php):

<?php // logout.php session_start(); // 销毁会话中的所有变量 $_SESSION = array(); // 销毁会话 session_destroy(); // 重定向到登录页 header("location: index.php"); exit; ?>

5.2 管理员后台 - 员工管理

这是系统的核心CRUD功能。我们以admin/employees.php为例,展示列表、添加、编辑、删除功能。

<?php // admin/employees.php $page_title = "员工管理"; require_once('../includes/auth.php'); requireAdmin(); // 只有管理员能访问 include('../includes/header.php'); require_once('../config/database.php'); // 处理删除请求 if(isset($_GET['delete_id']) && !empty($_GET['delete_id'])){ $delete_id = trim($_GET['delete_id']); // 注意:由于外键约束,删除员工会级联删除 users 和 salaries 表中的记录 $sql = "DELETE FROM employees WHERE id = ?"; if($stmt = mysqli_prepare($link, $sql)){ mysqli_stmt_bind_param($stmt, "i", $param_id); $param_id = $delete_id; if(mysqli_stmt_execute($stmt)){ $_SESSION['success'] = "员工记录已成功删除。"; header("location: employees.php"); exit(); } else{ $_SESSION['error'] = "删除失败,请稍后再试。"; } mysqli_stmt_close($stmt); } } // 获取所有员工信息,并关联部门名称 $sql = "SELECT e.*, d.name as department_name FROM employees e LEFT JOIN departments d ON e.department_id = d.id ORDER BY e.id DESC"; $result = mysqli_query($link, $sql); ?> <div class="d-flex justify-content-between align-items-center mb-4"> <h2>员工管理</h2> <a href="employee_add.php" class="btn btn-success">+ 添加新员工</a> </div> <?php // 显示成功/错误消息 if(isset($_SESSION['success'])){ echo '<div class="alert alert-success">' . $_SESSION['success'] . '</div>'; unset($_SESSION['success']); } if(isset($_SESSION['error'])){ echo '<div class="alert alert-danger">' . $_SESSION['error'] . '</div>'; unset($_SESSION['error']); } ?> <div class="table-responsive"> <table class="table table-bordered table-striped table-hover"> <thead class="table-dark"> <tr> <th>ID</th> <th>工号</th> <th>姓名</th> <th>部门</th> <th>职位</th> <th>邮箱</th> <th>电话</th> <th>入职日期</th> <th>操作</th> </tr> </thead> <tbody> <?php if(mysqli_num_rows($result) > 0){ while($row = mysqli_fetch_assoc($result)){ echo "<tr>"; echo "<td>" . $row['id'] . "</td>"; echo "<td>" . htmlspecialchars($row['employee_id']) . "</td>"; echo "<td>" . htmlspecialchars($row['name']) . "</td>"; echo "<td>" . htmlspecialchars($row['department_name'] ?? '未分配') . "</td>"; echo "<td>" . htmlspecialchars($row['position']) . "</td>"; echo "<td>" . htmlspecialchars($row['email']) . "</td>"; echo "<td>" . htmlspecialchars($row['phone']) . "</td>"; echo "<td>" . $row['hire_date'] . "</td>"; echo '<td> <a href="employee_edit.php?id=' . $row['id'] . '" class="btn btn-sm btn-warning">编辑</a> <a href="employees.php?delete_id=' . $row['id'] . '" class="btn btn-sm btn-danger" onclick="return confirm(\'确定要删除员工 ‘' . htmlspecialchars($row['name']) . '’ 吗?此操作不可逆。\');">删除</a> </td>'; echo "</tr>"; } } else { echo '<tr><td colspan="9" class="text-center">暂无员工数据。</td></tr>'; } mysqli_free_result($result); ?> </tbody> </table> </div> <?php mysqli_close($link); include('../includes/footer.php'); ?>

添加员工页面 (admin/employee_add.php) 的关键表单处理部分:

// ... 页面头部和权限检查 ... if($_SERVER["REQUEST_METHOD"] == "POST"){ // 接收并清理数据 $employee_id = trim($_POST['employee_id']); $name = trim($_POST['name']); $email = trim($_POST['email']); // ... 接收其他字段 ... // 验证数据 if(empty($employee_id) || empty($name) || empty($email)){ $error = "工号、姓名和邮箱为必填项。"; } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) { $error = "邮箱格式无效。"; } else { // 检查工号和邮箱是否已存在 $check_sql = "SELECT id FROM employees WHERE employee_id = ? OR email = ?"; if($check_stmt = mysqli_prepare($link, $check_sql)){ mysqli_stmt_bind_param($check_stmt, "ss", $employee_id, $email); mysqli_stmt_execute($check_stmt); mysqli_stmt_store_result($check_stmt); if(mysqli_stmt_num_rows($check_stmt) > 0){ $error = "该工号或邮箱已被使用。"; } else { // 插入数据 $sql = "INSERT INTO employees (employee_id, name, gender, email, phone, address, department_id, position, hire_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; if($stmt = mysqli_prepare($link, $sql)){ mysqli_stmt_bind_param($stmt, "ssssssiss", $param_employee_id, $param_name, $param_gender, $param_email, $param_phone, $param_address, $param_dept, $param_position, $param_hire_date); // 绑定参数 $param_employee_id = $employee_id; $param_name = $name; $param_gender = $_POST['gender']; $param_email = $email; $param_phone = $_POST['phone']; $param_address = $_POST['address']; $param_dept = !empty($_POST['department_id']) ? $_POST['department_id'] : NULL; $param_position = $_POST['position']; $param_hire_date = $_POST['hire_date']; if(mysqli_stmt_execute($stmt)){ $new_employee_id = $employee_id; // 可选:同时为这位员工创建一个默认的登录用户 // $default_password = '123456'; // 应改为随机生成 // $hashed_password = password_hash($default_password, PASSWORD_DEFAULT); // $user_sql = "INSERT INTO users (employee_id, username, password_hash, role) VALUES (?, ?, ?, 'employee')"; // ... 执行插入用户 ... $_SESSION['success'] = "员工添加成功。"; header("location: employees.php"); exit(); } else{ $error = "执行SQL语句时出错。"; } mysqli_stmt_close($stmt); } } mysqli_stmt_close($check_stmt); } } } // ... 显示表单的HTML代码 ...

5.3 员工前端 - 个人信息与薪资查询

员工登录后,只能查看和修改自己的信息。

员工仪表板 (employee/index.php):

<?php // employee/index.php $page_title = "员工控制台"; require_once('../includes/auth.php'); requireEmployee(); // 确保已登录 include('../includes/header.php'); ?> <div class="row"> <div class="col-md-12"> <div class="card"> <div class="card-header"> <h5>欢迎回来,<?php echo htmlspecialchars($_SESSION['employee_name']); ?>!</h5> </div> <div class="card-body"> <p>您的工号:<strong><?php echo htmlspecialchars($_SESSION['employee_id']); ?></strong></p> <p>您的角色:<span class="badge bg-info"><?php echo $_SESSION['role']; ?></span></p> <hr> <div class="row"> <div class="col-md-6"> <div class="card text-center"> <div class="card-body"> <h5 class="card-title">我的档案</h5> <p class="card-text">查看和编辑您的个人信息。</p> <a href="profile.php" class="btn btn-primary">前往</a> </div> </div> </div> <div class="col-md-6"> <div class="card text-center"> <div class="card-body"> <h5 class="card-title">我的薪资</h5> <p class="card-text">查询您的历史薪资记录。</p> <a href="my_salary.php" class="btn btn-primary">前往</a> </div> </div> </div> </div> </div> </div> </div> </div> <?php include('../includes/footer.php'); ?>

员工个人信息页面 (employee/profile.php)的逻辑与管理员编辑类似,但关键区别在于 SQL 查询的WHERE条件:

// 在 profile.php 中,查询条件基于当前登录的员工 $sql = "SELECT e.*, d.name as department_name FROM employees e LEFT JOIN departments d ON e.department_id = d.id WHERE e.employee_id = ?"; // 绑定参数时使用 $_SESSION['employee_id'] mysqli_stmt_bind_param($stmt, "s", $_SESSION['employee_id']);

6. 系统安全与最佳实践

一个可用的系统还必须是一个安全的系统。以下是必须实施的几个关键点:

6.1 SQL注入防护

我们已经在代码中使用了预处理语句 (Prepared Statements),这是防止 SQL 注入最有效的方法。永远不要将用户输入直接拼接到 SQL 字符串中。

错误示例(危险!):

$sql = "SELECT * FROM users WHERE username = '" . $_POST['username'] . "' AND password = '" . $_POST['password'] . "'";

正确示例(使用预处理):

$sql = "SELECT * FROM users WHERE username = ? AND password_hash = ?"; $stmt = mysqli_prepare($link, $sql); mysqli_stmt_bind_param($stmt, "ss", $username, $hashed_password);

6.2 密码存储

绝对禁止明文存储密码。必须使用单向哈希函数。

  • 存储密码时:使用password_hash()。
    $hashed_password = password_hash($raw_password, PASSWORD_DEFAULT);
  • 验证密码时:使用password_verify()。
    if (password_verify($input_password, $stored_hash)) { // 密码正确 }

6.3 会话安全

  • 使用session_start()开启会话。
  • 登录后立即重置会话 ID:session_regenerate_id(true)可以防止会话固定攻击。
  • 设置会话过期时间:可以在php.ini中配置,或通过代码控制。
  • 退出时销毁会话:如logout.php所示。

6.4 输出转义

为了防止跨站脚本攻击(XSS),所有从数据库或用户输入中取出并显示在 HTML 页面的数据,都必须使用htmlspecialchars()函数进行转义。

echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');

6.5 权限控制

本系统通过includes/auth.php中的requireAdmin()和requireEmployee()函数实现了简单的页面级权限控制。在实际更复杂的系统中,可能还需要更细粒度的功能级权限控制(RBAC)。

7. 部署与优化建议

7.1 基础部署

  1. 购买域名与服务器:可以选择云服务器(如阿里云ECS、腾讯云CVM)。
  2. 配置LAMP/LNMP环境:在服务器上安装 Linux, Apache/Nginx, MySQL, PHP。
  3. 上传代码:使用 FTP/SFTP 或 Git 将项目代码上传到服务器的 Web 目录(如/var/www/html)。
  4. 导入数据库:将本地开发时导出的 SQL 文件在服务器上导入。
  5. 修改配置文件:更新config/database.php中的数据库连接信息(服务器地址、用户名、密码)。
  6. 设置文件权限:确保 Web 服务器用户(如www-data)对项目目录有适当的读写权限(通常755用于目录,644用于文件),对上传目录可能需要775。

7.2 性能与安全优化

  1. 启用 HTTPS:为域名申请 SSL 证书(Let‘s Encrypt 提供免费证书),强制所有流量使用 HTTPS。
  2. 配置 Web 服务器:
    • Apache:启用mod_rewrite进行 URL 重写,隐藏.php扩展名。
    • Nginx:配置正确的try_files和 PHP-FPM 转发。
  3. PHP 配置:
    • 在生产环境php.ini中,设置display_errors = Off和log_errors = On。
    • 调整upload_max_filesize和post_max_size以适应需求。
    • 启用 OpCache 以提升 PHP 脚本执行速度。
  4. MySQL 优化:为经常查询的字段(如employee_id,email,department_id)建立索引。定期进行数据库备份。
  5. 代码层面:
    • 将常量配置(如数据库信息)移出 Web 可访问目录。
    • 实现更完善的错误处理与日志记录。
    • 对管理功能增加操作日志。

7.3 功能扩展方向

这个基础系统可以作为一个起点,根据实际需求进行扩展:

  1. 考勤管理模块:添加打卡、请假、加班申请与审批流程。
  2. 公告通知系统:管理员发布公告,员工端显示。
  3. 文件共享:部门或公司级别的文档上传与下载。
  4. 报表统计:使用图表库(如 Chart.js)可视化员工人数、部门分布、薪资成本等数据。
  5. API 接口:为未来可能的移动端 App 提供数据接口。
  6. 更复杂的权限系统:实现基于角色的访问控制(RBAC),支持多级管理员和权限组。

开发过程中,务必遵循“先完成,再优化”的原则。首先确保核心流程跑通,然后再逐步迭代,增加新功能和优化用户体验。

相关新闻

  • AI招聘工具核心技术解析与落地实践
  • C++类设计进阶:从RAII到移动语义的实战指南
  • MotionBERT:跨模态人体运动识别统一框架解析

最新新闻

  • 凉山黄金上门回收哪家靠谱?西昌、会理、德昌正规黄金回收门店盘点,2026 年 7 月实时金价参考 - 不晚生活号
  • C++并发编程实战指南:从数据竞争到线程池的完整解决方案
  • 基于LangGraph和FastAPI的AI智能体开发实战
  • 嵌入式通信实战:从I2C与CAN寄存器视角掌握硬件对话
  • AI如何解决毕业论文写作痛点:选题到答辩全流程优化
  • 公众号接入大模型:智能客服与内容生成实战指南

日新闻

  • 从国家条件到买方清单,深入理解 ABAP CDS 单值过滤器派生
  • 2026 年当下,齐齐哈尔专业的不锈钢闸门批发厂家哪个好,揭秘!这个工业“铁门”如何实现成本翻倍的效率提升? - 行业甄选官
  • 2026阳极氧化加工厂推荐:从设备规模看硬质氧化技术的成熟应用推荐百正机械 - 栗子测评

周新闻

  • SaaS软件行业GEO实践:AI搜索时代的品牌可见性与获客新路径
  • 什么是PCTFE?医药高端包装的“防潮王牌“材料
  • 【JVM调优实战】16-可视化利器-JConsole-VisualVM-JMC

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号