# MRBS 等保2.0二级整改 · 生产上线步骤(PHP+MySQL 云空间)
适用版本:MRBS 1.12.2(会议预定系统)|整改日期:2026-09-08
本地已验证:全部文件 `php -l` 通过;php -S 端到端冒烟测试通过(登录锁定/强制改密/审计日志/水印/禁止匿名)。
---
## ⚠️ 0. 上线前必须确认(先看这里)
1. **PHP 版本必须 ≥ 8.0**
MRBS 1.12.2 官方代码已使用 PHP 8.0 语法(`#[\SensitiveParameter]` attribute),
PHP 7.x 会直接解析失败(README 里的 PHP 7.2 要求已过时)。请在云空间控制面板确认/切换到 PHP 8.0+(建议 8.1~8.3)。
2. **数据库备份已就绪**:`mrbs_users_bak_20260908.sql`(本包内,14 用户备份,整改前导出)。
3. **存量用户首登强制改密**:14 个存量用户 `password_changed_at=0`,上线后首次登录会被强制要求改密。
建议先给管理员(jeremy)走一遍流程,确认无误再通知全员。
4. **生产 config.inc.php 若有个性化定制**:不要整文件覆盖生产 config,
只把「等保二级整改配置」段(见下方第 2 步说明)追加到生产 config 末尾,并核对没有重名变量冲突。
---
## 1. 备份生产
- 用云空间文件管理/FTP 把整个 MRBS 站点目录下载备份(至少备份以下将被覆盖的文件):
`config.inc.php`、`Themes/default/header.inc`、`edit_users.php`、`mrbs_auth.inc`、
`lib/MRBS/Auth/AuthDb.php`、`lib/MRBS/Session/SessionWithLogin.php`、`lang/lang.zh-hans`、`lang/lang.en`
- 数据库再备份一次(phpMyAdmin 导出 hotel 库,或本包 SQL 备份文件为基础):
## 2. 上传文件(patch/ 目录,保持相对路径)
| 文件 | 说明 |
|---|---|
| `config.inc.php` | **先比对生产现有 config**。若生产 config 与本地完全一致可直接覆盖;若有差异,仅追加"等保二级整改配置"段(从 `/* ====================== 等保二级整改配置(2026-09-08) ====================== */` 到文件尾),并确认 `$pwd_policy/$login_lock_*/$pwd_max_age/$audit_log_file/$watermark_enabled` 未与生产已有变量重名 |
| `change_password.php` | 新增:自助改密页(放 web/ 根目录) |
| `mrbs_auth.inc` | 修改:change_password.php 白名单(level 0 可访问) |
| `edit_users.php` | 修改:3 个新安全列不进表单/列表/保存路径;管理员设密→用户下次登录强制改密 |
| `lib/MRBS/Audit.php` | 新增:安全审计日志类(自动建目录、20MB 轮转) |
| `lib/MRBS/Auth/AuthDb.php` | 修改:登录失败锁定、口令 90 天有效期、改密逻辑 |
| `lib/MRBS/Session/SessionWithLogin.php` | 修改:登录审计 + 强制改密标记 |
| `Themes/default/header.inc` | **重要**:整文件替换为官方 v1.12.2 版 + 等保补丁(修版本混杂致命 bug)。若生产主题有定制请先备份 diff 后再合并 |
| `lang/lang.zh-hans`、`lang/lang.en` | 修改:新增等保词条 |
| `audit/.htaccess` | 新增:审计目录禁止 Web 访问 |
上传后目录权限建议:`audit/` 755(或 775),站点文件 644、目录 755(按云空间习惯)。
## 3. 执行数据库脚本(phpMyAdmin 或 mysql 命令行)
对 `hotel` 库执行 `security_upgrade_20260908.sql`:
- 给 `mrbs_users` 增加 3 列:`password_changed_at`(int) / `failed_logins`(int) / `locked_until`(int),默认 0
- 脚本含幂等处理与回滚语句(脚本顶部注释有说明)
- 若生产库此前已手工加过列,脚本会跳过(先看脚本内 `IF NOT EXISTS` 写法,MySQL 5.7 需按脚本实际内容执行)
## 4. 功能验证清单(上线后逐项过)
1. 未登录访问任意页面 → 跳转/显示登录页(禁止匿名 ✓)
2. 登录页标题/样式正常,无 PHP 报错(确认 header.inc 替换成功)
3. 管理员 jeremy 登录 → **被强制跳转到修改密码页** → 用符合策略的新密码(≥8位含大小写数字特殊字符)改密 → 成功回到系统
4. 菜单栏出现"修改密码"入口
5. 打开任意页面 → 屏幕有斜纹水印(姓名+IP+时间,防截图溯源)
6. 连续输错 5 次密码 → 提示"账号已被临时锁定,请约 15 分钟后重试"(换一个测试账号试,别锁管理员)
7. 查看 `audit/security_audit.log` 是否有登录成功/失败记录(浏览器直接访问该路径应 403)
8. 旧密码登录被拒、新密码可登录
9. 15~30 分钟不操作自动退出(可临时把 `inactivity_expire_time` 调小验证后改回)
## 5. 云空间部署层加固(等保要求,云空间能力范围内)
**A. HTTPS 强制(必做)**
- 云空间控制面板申请免费 SSL 证书(或上传已有证书),开启"强制 HTTPS 跳转"
- MRBS 检测 HTTPS 后自动给会话 Cookie 加 Secure 属性(代码已支持)
**B. 安全响应头(Apache 云空间支持 .htaccess 时,放到站点根 .htaccess)**
```apache
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Content-Security-Policy "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'"
# 屏蔽常见敏感路径
Require all denied
```
(若云空间是 Nginx 或面板管理,把响应头配到对应 server 段。CSP 若影响 MRBS 功能再放宽并记录。)
**C. PHP 配置**:云空间若可配 php.ini(或 .user.ini):
```ini
session.cookie_httponly = 1
session.use_strict_mode = 1
expose_php = Off
display_errors = Off
log_errors = On
```
(会话超时已在 MRBS config 层控制,无需改 session.gc_maxlifetime)
**D. 审计日志留存**:云空间无法装 logrotate 时——Audit.php 已内置 20MB 自动轮转(保留 .old 一份);
建议每季度通过 FTP 下载 audit/ 目录归档(等保要求日志留存 ≥ 6 个月,测评时会查)。
**E. 数据库备份**:云空间 phpMyAdmin 定期导出 + 下载异地保存(等保要求备份留存 ≥ 6 个月)。
可配合云空间控制面板的自动备份功能(如有)。
## 6. 回滚方案
- 用第 1 步备份覆盖回原文件(或 patch 包里文件反向替换)
- SQL 回滚:`ALTER TABLE mrbs_users DROP COLUMN password_changed_at, DROP COLUMN failed_logins, DROP COLUMN locked_until;`
(注意:若回滚后有人已改密,password_hash 已更新为 bcrypt,与旧代码兼容——MRBS 支持 bcrypt 校验,无需担心)
- 删除 change_password.php、lib/MRBS/Audit.php、audit/ 目录
---
## 附:本次整改内容速览(测评自述用)
| 等保要求 | 实现 |
|---|---|
| 身份鉴别-复杂度 | `$pwd_policy` 8位+大小写+数字+特殊,管理端/重置/自助改密全链路生效 |
| 身份鉴别-登录失败处理 | 连续失败 5 次锁定 15 分钟(`failed_logins`/`locked_until` 列),防暴力破解 |
| 身份鉴别-登录超时 | 空闲 30 分钟自动退出 + 绝对 12 小时过期(原 30 天/永不) |
| 身份鉴别-定期更换 | 口令 90 天有效期,到期/首登强制改密(`password_changed_at` 列 + 强制跳转) |
| 身份鉴别-双因素 | 二级可不要求(若测评要求再议) |
| 访问控制-匿名 | `$auth['deny_public_access']=true` 全站强制登录 |
| 安全审计 | 登录成功/失败/锁定、改密等事件 JSON Lines 落盘 `audit/security_audit.log`,20MB 轮转 |
| 边界防护-防截屏 | 屏幕水印:姓名(账号)+IP+实时时间斜纹平铺 |
| 数据保密-传输 | HTTPS 强制 + Cookie Secure/HttpOnly/SameSite=Strict(MRBS 已有) |
| 其余已有基线 | bcrypt 存储、CSRF token、SQL 注入防护(PDO)、XSS 输出转义、四级权限、密码重置流程安全(一次性 key+过期) |
已同步修的重大问题:Themes/default/header.inc 原为 1.11.x 旧版(引用 1.12 已删除函数,任何页面必报错),本包内已替换为官方 v1.12.2 + 等保补丁版。