页脚入口与安装向导;加固管理员口令存储

需求落实:
1. 页脚常驻「管理后台」链接,不用再手敲 admin.php。
2. 页脚「由 FeedLite 驱动」中的 FeedLite 改为超链接(指向开源仓库);
   后台新增「页脚」设置组,可关闭整句(关闭后只留管理后台链接),也可改链接地址。
3. 管理员口令存储方式在后台如实展示:数据库 settings.admin.password_hash,
   存 bcrypt 单向哈希(不可逆),明文不落盘。
4. 新增安装向导 install.php:data/ 下没有数据库时自动 302 引导;
   体检环境 -> 填站点信息与口令 -> 生成 config.php -> 建库建表 -> 完成。

顺带修掉一个真实安全隐患:
  config.php 里的出厂占位口令 CHANGE_ME_admin 原先可被当作有效口令登录后台
  (等于公开仓库里就写着线上后门口令)。现改为占位/空值一律拒绝,
  未设口令时后台明确提示去安装向导,不再含糊报「口令不正确」。

实现要点:
- 新增 fb_cfg_file():只读配置文件、不叠加 settings 表、绝不触达数据库。
  「是否已安装」以数据库文件是否存在为判据,而 fb_cfg() 读 settings 会触发
  fb_db() 就地建库 —— 那会把安装态自己造出来,所以判定必须走不碰库的通道。
- bootstrap 只在已安装时建库;未安装则 302 到 install.php(CLI 下报错退出)。
- fb_settings_flat() 在未安装时直接返回空,杜绝任何隐式建库。
- install.php 用文本级替换生成 config.php,保留全部注释与 OSS/SMTP 段落;
  生成的 PHP 用 token_get_all(TOKEN_PARSE) 校验后才落盘。
- 页脚链接只放行 http/https,后台保存时校验(防 javascript: 伪协议)。
- style.css 页脚行改 flex,版本号 v6 -> v7。

验证:
- php -l 全量通过;现有回归 25/25、附件专项 13/13 保持通过。
- 安装向导专项 60/60(含「明文口令未写入任何文件」「数据库字节里搜不到明文」)。
- 反向验证:撤销三处修复后对应断言确实失败(断言非装饰)。
- 几何检查:本机 15/15 + 页脚专项全过;线上真实 URL 15/15 + 页脚专项全过。
- 线上真机冒烟 22/22。
This commit is contained in:
2026-09-28 22:53:55 +08:00
parent 1401ad899b
commit 27187b38f1
8 changed files with 654 additions and 39 deletions
+67 -7
View File
@@ -25,6 +25,7 @@ feedback/
├─ thread.php 问题详情 + 回复(含"官方答复"与状态管理、附件展示)
├─ new.php 发布新问题(含图片 / 视频上传)
├─ admin.php 管理后台(口令登录:审核 / 管理全部问题 / 站点设置 / 操作日志)
├─ install.php 安装向导(数据库不存在时自动引导进来;装完建议删除)
├─ upload.php 附件上传接口(两步:领对象键 → 收文件本体,local 落盘 / OSS 代理 PUT)
├─ media.php 附件代理输出(私有桶 + 内网 Endpoint 下图片/视频的唯一对外读取通道,带鉴权与 Range)
├─ captcha.php "换一题"用的人机验证刷新接口(返回 JSON)
@@ -60,8 +61,9 @@ feedback/
chown -R www:www /www/wwwroot/你的域名/feedback
chmod -R 755 /www/wwwroot/你的域名/feedback/data
```
4. 首次访问 `https://你的域名/feedback/` 会自动建库建表。
5. **打开 `config.php`,修改这三项**(务必!):
4. 首次访问 `https://你的域名/feedback/` —— 此时 `data/` 下还没有数据库,
程序会**自动把你送到安装向导 `install.php`**(见 **第二节之二**)。按向导填完即装好。
5. 若你更愿意手工配置:从 `config.example.php` 复制一份为 `config.php`,改掉这三项后刷新页面即可建库。
- `admin_password` —— 管理员口令(回复时填入即以「官方」身份答复;也是审核后台 `admin.php` 的登录口令)
- `api_token` —— 读取接口的令牌(自己设一串随机字符)
- `ip_salt` —— 随机字符串(用于给访客 IP 做哈希)
@@ -76,11 +78,50 @@ feedback/
---
## 二之二、安装向导(`install.php`)
**什么时候出现**:只要 `data/` 下还没有数据库文件,访问站点的任何页面都会 302 到 `install.php`。
反过来,数据库一旦存在,向导就只显示「已经装好了」,**不会**覆盖任何数据。
向导分三步,一屏走完:
1. **环境体检** —— PHP 版本(≥7.4)、必需扩展(`pdo_sqlite` / `openssl`)、
`站点根 / data / uploads` 目录可写性、`config.example.php` 是否在。有任一项不过就拒绝提交。
2. **填写站点信息** —— 站点标题、站点描述、官方邮箱、站点根地址(后两项可留空)。
3. **设置管理员口令** —— 至少 8 位;也可以留空、装完后在后台补设(**补设之前后台登不进去**)。
提交后向导会:
- 生成 `config.php`(在 `config.example.php` 的**文本**上逐项替换,注释与 OSS / SMTP 段落原样保留);
- 自动填好 `api_token` 与 `ip_salt`(随机串,不用你操心);
- 建库建表;
- 把口令以 **bcrypt 哈希**写入数据库 `settings` 表 —— **明文不进 `config.php`、不进任何文件**。
**装完请做两件事**:
1. **删掉 `install.php`**(已安装态下它会拒绝重装,但少一个入口少一分风险)。
2. 若口令留空了,进后台「站点设置 → 登录口令」补设一个。
> 想重装(例如换了数据库位置):先手工移走 `data/feedback.db`,再刷新即可。
> 向导**不会**替你删除任何数据。
---
## 三、首页加链接
已在官网 `index.html` 的**顶部导航**与**页脚「产品」列**加入「问题反馈」入口,指向 `feedback/`。
(本地文件:`(你的站点首页)`)
### 页脚里有「管理后台」入口
站点页脚固定显示一个「管理后台」链接(指向 `admin.php`),不需要手动在地址栏敲文件名。
旁边那句「由 FeedLite 驱动」可以关掉:
- 后台「**站点设置 → 页脚**」→ 取消勾选「在页脚显示『由 FeedLite 驱动』」
→ 页脚只剩「管理后台」链接;
- 同一处还能改「FeedLite」二字指向的地址(默认是本项目开源仓库)。
只接受 `http://` / `https://` 开头的网址。
---
## 四、邮件通知(SMTP)
@@ -566,23 +607,42 @@ curl "https://你的域名/feedback/api.php?token=XXX&action=digest&status=open"
- `data/` 目录用 `.htaccess` 拒绝一切直接访问;请勿删除该文件。
### 更换管理员口令 / 令牌
直接修改 `config.php` 即可,无需改代码。
- **管理员口令**:登录后台后在「站点设置 → 登录口令」里改(至少 8 位)。改完即以 bcrypt 哈希存进数据库,`config.php` 里的 `admin_password` 只是「未设置」时的初始值通道。
- **令牌 `api_token` / 盐 `ip_salt`**:这两项没有后台界面,改 `config.php` 即可,无需改代码。
### 口令存在哪、是否加密(重要)
| 状态 | 存在哪 | 是否加密 | 怎么变成下一档 |
|---|---|---|---|
| 刚 clone 下来、没装 | `config.php` 的 `admin_password` = `CHANGE_ME_admin` | 明文,但**该值已被程序明确禁用**,无法登录 | 跑 `install.php`,或到后台设定口令 |
| 手工在 `config.php` 指定了口令 | `config.php` 的 `admin_password` | **明文**(配置文件里) | 登录一次后到后台改一次口令 → 转为数据库哈希 |
| 正常状态(推荐) | 数据库 `settings` 表的 `admin.password_hash` | **是**,bcrypt 单向哈希(`$2y$…`),不可逆 | 已是最终形态 |
- 后台「站点设置 → 登录口令」会把当前处于哪一档**如实显示出来**,Linux 下也能直接查库确认。
- 明文口令**永远不会**由安装向导或后台写进任何文件:向导只把哈希写进数据库。
- 怀疑口令泄露:到后台改掉即可。若把数据库里 `admin.password_hash` 这一行删掉,
会退回使用 `config.php` 的值(也因此回到明文档,建议删完立刻重新设定)。
---
## 七之二、`config.php` 里的三个"必改"参数是什么
这三项都写在 `config.php` 的「安全」段落里,出厂值都是 `CHANGE_ME_...` 占位符,**上线前必须换成自己的随机值**。
> **走安装向导的话,这一段可以跳过**:`install.php` 会替你生成 `config.php`,
> 并自动填好 `api_token` 与 `ip_salt`(都是随机串),管理员口令则直接以哈希入库、不进文件。
> 下面这些是「想手工配置」时看的说明。三项出厂值都是 `CHANGE_ME_...` 占位符。
### `admin_password` —— 登录口令(初始值)
### `admin_password` —— 登录口令(初始值,可留空)
- **干什么用**:两个地方共用同一串,所以必须一致 ——
- **干什么用**:两个地方共用同一串 ——
① 详情页回复框里填它 → 以「官方」身份发言;
② `/feedback/admin.php` 登录 → 进管理后台(审核、回复、改状态、删帖、改站点设置)。
- **建议**:**登录后台后在「站点设置 → 修改登录口令」里改成你自己的一串**(至少 8 位)。
- **建议**:优先用安装向导;若手工配,**登录后台后立刻在「站点设置 → 登录口令」里改成你自己的一串**(至少 8 位)。
改完会以 `password_hash()` 存进数据库,`config.php` 里这行就只是"出厂默认值"了 ——
⚠️ 此时改 `config.php` **不会**再影响登录口令,忘了新口令就去数据库把 `settings` 表里
`admin.password_hash` 这一行删掉,即可退回用 `config.php` 里的值。
- ⚠️ **占位值 `CHANGE_ME_admin` 已被程序明确禁用**(空值同样):也就是说,**clone 下来不做任何配置时,
后台任何人都登不进去** —— 这是刻意的,避免"文档里公开的默认口令"变成线上后门。
- **它不是什么**:站点面向访客没有账号体系,也没有访客登录页。它只是一串比对用的口令 ——
表单里填的内容与库里的哈希(或 `config.php` 里的值)比对一次,一致就按官方处理。