Jandres25/Encriptacion_PHP
GitHub: Jandres25/Encriptacion_PHP
一个自定义的轻量级 PHP MVC 认证系统,提供安全的用户登录、权限管理及完整的管理后台 CRUD 功能。
Stars: 0 | Forks: 0
# SecureAuth — PHP MVC 认证系统
[](https://github.com/Jandres25/Encriptacion_PHP/releases/tag/1.9.0)
[](https://github.com/Jandres25/Encriptacion_PHP/actions/workflows/tests.yml)
[](https://php.net/)
[](https://github.com/PHPMailer/PHPMailer)
[](LICENSE)
基于 Composer、轻量级 router 和基于角色的访问控制构建的自定义 PHP MVC 认证系统。
## 功能
- 自定义 MVC 架构 — `App\Core\Router`,抽象 `Controller` 和 `Model`,通过 Composer 实现 PSR-4 自动加载
- 安全登录,使用 bcrypt 密码哈希(`password_hash()` / `password_verify()`)
- 所有 POST 表单均启用 **CSRF 防护**,通过 `App\Core\Csrf` 使用 `hash_equals()` 进行 token 比对
- **防止会话固定** — 每次成功登录时执行 `session_regenerate_id(true)`
- 通过 **Remember Me** 实现持久登录 — `HttpOnly` / `SameSite=Strict` cookie;token 在数据库中以 SHA-256 哈希格式存储
- 非活动状态下的自动 **会话超时**,并清理 remember cookie
- 通过电子邮件进行密码恢复,使用存储为 SHA-256 哈希的一次性过期 token(PHPMailer + STARTTLS)
- **用户个人资料** — 经过身份验证的用户可以在 `/profile` 修改其姓名、电子邮件和用户名,或更改密码;每个操作都有受 CSRF 保护的独立表单
- 管理员用户管理 — 具备基于角色的访问控制(`AuthMiddleware`)的完整 CRUD 功能
- `App\Config\Database` 单例 — 每个 request 单一 `\mysqli` 连接
- 用户列表的基于文件的缓存,在写入时自动失效
- **账户锁定** — N 次登录失败后自动锁定账户;可通过 `.env` 配置阈值和持续时间
- **HTTP 安全标头** — 通过 `.htaccess` 中的 `mod_headers` 设置 `X-Frame-Options`、`X-Content-Type-Options`、`Referrer-Policy`、`Content-Security-Policy` 等;HSTS 已为 HTTPS 准备就绪
- **安全会话 cookie** — `session_start_secure()` 辅助函数在每次会话启动时强制执行 `HttpOnly`、`SameSite=Strict` 以及条件性的 `Secure` 标志
- **自定义错误页面** — 契合应用设计风格的 404、403 和 500 视图;独立运行(无数据库依赖)
- **集成测试套件** — 针对真实 MySQL 数据库的 40 个 PHPUnit 测试;通过 GitHub Actions 进行 CI
- 所有 CRUD 和身份验证操作均使用 SweetAlert2 toast 通知
- 逐页注入 asset — 共享布局中的 `$pageStyles` / `$pageScripts` 数组
- 共享布局系统 — `header.php` / `footer.php` 接受 `$pageTitle`、`$favicon`、`$bodyClass`、`$useDataTables`
- 页脚通过 `APP_VERSION` 环境变量显示应用版本
## 环境要求
- PHP >= 8.2
- MySQL / MariaDB
- 启用 `mod_rewrite` 的 Apache(推荐使用 XAMPP)
- Composer
- 带有应用专用密码的 Gmail 账户(或任何 SMTP 提供商)
## 安装说明
1. Clone 该 repository:
```
git clone https://github.com/Jandres25/Encriptacion_PHP.git
cd Encriptacion_PHP
```
2. 安装依赖项:
```
composer install
```
3. 复制并配置环境文件:
```
cp .env.example .env
```
使用您的凭证编辑 `.env`:
```
DB_HOST=localhost
DB_USERNAME=root
DB_PASSWORD=
DB_DATABASE=login
SMTP_HOST=smtp.gmail.com
SMTP_USERNAME=your@gmail.com
SMTP_PASSWORD=your_app_password
SMTP_PORT=587
APP_URL=http://localhost/Encriptacion_PHP/public
APP_TIMEZONE=America/Bogota
APP_VERSION=1.9.0
CACHE_ENABLED=true
CACHE_TTL_USERS=60
REMEMBER_ME_ENABLED=true
REMEMBER_ME_TTL=2592000
SESSION_TIMEOUT=1800
LOGIN_LOCKOUT_ENABLED=true
LOGIN_MAX_ATTEMPTS=5
LOGIN_LOCKOUT_MINUTES=15
```
4. 导入数据库 schema:
```
mysql -u root -p < database/schema.sql
```
5.(可选)加载示例数据:
```
mysql -u root -p < database/seeds.sql
```
6. 将项目放置在服务器的 web 根目录中(例如 XAMPP 中的 `htdocs/`),然后在浏览器中打开 `APP_URL`。
## 项目结构
```
├── app/
│ ├── Config/
│ │ ├── autoload.php # Bootstrap: timezone, cache, DB, session, restoreFromCookie()
│ │ ├── cache.php # Cache bootstrap + appCache() helper
│ │ ├── config.php # Loads .env via phpdotenv; defines APP_URL + env()
│ │ └── database.php # Database singleton — Database::getConnection()
│ ├── Controller/
│ │ ├── AuthController.php # login, logout, forgotPassword, resetPassword
│ │ ├── HomeController.php # Dashboard — applies timeout + auth middleware
│ │ ├── ProfileController.php # profile(), changePassword() — any authenticated user
│ │ └── UserController.php # Full user CRUD — guarded by admin middleware
│ ├── Core/
│ │ ├── Auth.php # Credential verify, remember-me tokens, password reset tokens
│ │ ├── Controller.php # Abstract base — render(), redirect(), verifyCsrf()
│ │ ├── Csrf.php # CSRF token generation and verification
│ │ ├── Model.php # Abstract base — holds protected \mysqli $db
│ │ └── Router.php # GET/POST route registration and dispatch
│ ├── Middleware/
│ │ └── AuthMiddleware.php # Static guards: auth(), admin(), timeout()
│ ├── Model/
│ │ ├── LoginAttempt.php # Account lockout — atomic insert/update, lock check, clear
│ │ └── User.php # All DB queries via MySQLi prepared statements
│ └── Service/
│ └── MailerService.php # PHPMailer encapsulation — SMTP via STARTTLS
├── database/
│ ├── schema.sql # Table definitions (users, password_resets, login_attempts)
│ ├── schema_test.sql # Table-only schema for test DB (no CREATE DATABASE)
│ └── seeds.sql # Sample data with bcrypt-hashed passwords
├── libs/
│ └── Cache/ # File-based cache implementation
├── public/
│ ├── css/ # bootstrap.css, estilo.css, all.min.css, layout-protected.css
│ ├── DataTables/ # DataTables JS bundle + Bootstrap 4 skin
│ ├── img/ # Images and icons
│ ├── js/ # jQuery, Bootstrap JS, Popper, SweetAlert2, users-*.js
│ ├── webfonts/ # FontAwesome webfonts
│ ├── .htaccess # Apache rewrite rules for clean URLs
│ └── index.php # Front controller
├── routes/
│ └── web.php # All route definitions
├── storage/
│ ├── .htaccess # Require all denied — blocks direct web access to cache files
│ └── cache/ # Runtime cache files (*.cache)
├── views/
│ ├── auth/ # login, forgot_password, reset_password (standalone, self-hosted assets)
│ ├── errors/ # 404.php, 403.php, 500.php + layout.php (standalone, no DB dependency)
│ ├── home/ # index.php — dashboard content (wrapped by shared layout)
│ ├── layouts/ # header.php, footer.php, messages.php
│ ├── profile/ # index.php — unified profile + change password view
│ └── user/ # index, create, edit (wrapped by shared layout)
├── tests/
│ ├── bootstrap.php # Test bootstrap — loads .env.testing, never starts session
│ ├── TestCase.php # Abstract base — DB connection, truncate, createUser()
│ ├── Unit/
│ │ └── UserTest.php # 14 integration tests for App\Model\User
│ └── Integration/
│ └── AuthTest.php # 19 integration tests for App\Core\Auth
├── .env.example # Environment variable template
├── phpunit.xml # PHPUnit 11 configuration
└── composer.json # Composer dependencies and PSR-4 autoload
```
## 用法
1. 在浏览器中打开 `http://localhost/Encriptacion_PHP/public/`
2. 使用预置的用户登录(例如用户名 `Admin`,密码 `Admin1234`)
3. 点击导航栏中的用户名以访问您的 **个人资料** — 编辑信息或更改密码
4. 管理员用户(`is_admin = 1`)可在导航栏看到 **用户** 链接 → 完整的 CRUD
5. 要找回密码,请点击登录页面上的“忘记密码?”
## URL 路由
所有路由均在 `routes/web.php` 中声明,并由 `App\Core\Router` 分发:
| URL | Controller method |
| --------------------------- | ---------------------------------- |
| `/` | `HomeController::index()` |
| `/login` | `AuthController::login()` |
| `POST /logout` | `AuthController::logout()` |
| `/forgot-password` | `AuthController::forgotPassword()` |
| `/reset-password?token=...` | `AuthController::resetPassword()` |
| `/profile` | `ProfileController::profile()` |
| `POST /profile/password` | `ProfileController::changePassword()` |
| `/users` | `UserController::index()` |
| `/users/create` | `UserController::create()` |
| `/users/edit?id=X` | `UserController::edit()` |
| `POST /users/delete` | `UserController::delete()` |
## 安全
- 使用 bcrypt 对密码进行哈希处理(`PASSWORD_DEFAULT`)
- 仅在成功执行 `password_verify()` 后设置会话;紧接着调用 `session_regenerate_id(true)` 以防止会话固定
- **安全会话 cookie** — `session_start_secure()` 辅助函数在每次会话启动时(包括登出和会话超时后)强制执行 `HttpOnly`、`SameSite=Strict` 以及(在 HTTPS 上)`Secure`
- **HTTP 安全标头** — 通过 `public/.htaccess` 中的 `mod_headers` 设置 `X-Frame-Options: DENY`、`X-Content-Type-Options: nosniff`、`Referrer-Policy`、`Content-Security-Policy`、`Permissions-Policy`;HSTS 已注释掉,为 HTTPS 做好准备
- 所有 POST 表单均启用 **CSRF token** — 通过 `App\Core\Csrf::token()` 生成,在每个 controller 中使用 `hash_equals()` 验证;每次成功验证后 **轮换 token**
- **登出仅限 POST** — 受 CSRF token 保护;防止通过 `