附件读取统一走 media.php 代理,真实地址不再暴露
无论附件存在本机 uploads/ 还是 OSS 私有桶,前台给浏览器的地址现在完全一致: media.php?k=<对象键>。界面上不再出现 uploads/ 真实路径,也不出现任何 bucket / endpoint / 签名痕迹。 - lib/attach.php:新增 fb_attach_proxy_url(),fb_attach_url() 与 fb_attach_thumb_url() 的本机分支一并改走代理(地址不落库、渲染现算, 对历史附件立即生效,无需迁移)。 - uploads/ 整目录禁止 Web 直读:附件只能经 media.php 出,真实物理路径 即便被猜到也取不到,同时绕不开 media.php 的可见性鉴权。 - 规则版本化自动升级:.htaccess 内埋 `# fb-local-guard: vN`, 旧版规则在任意请求时由 PHP(目录属主)整份重写。之所以不能靠部署覆盖: 部署账号对 uploads/ 无写权限,只有程序自己能改。 - 随包 uploads/.htaccess 改为程序产出的逐字节副本,并加断言防漂移 (否则线上会被自动升级覆盖,随包那份形同虚设)。 - 顺带修复真实源码泄漏:config.php.bak_<时间戳> 这类「非 .php 结尾、 但含源码」的备份文件此前可被公开下载。加固根 .htaccess: 去掉正则结尾锚点、补 .php[.\-_] 兜底、点名拒绝 config.php / oss.sts.php。 - media.php / upload.php / admin.php / README.md:文档与响应头同步。 验证:php -l 19 文件 0 失败;主回归 25/25、附件专项 22/22、安装向导 60/60、 统一代理渲染 7/7、反向验证 V1-V4 全被抓住;线上冒烟 30/30、 线上统一代理真机 13/13(OSS 私有桶 + 内网 endpoint 下上传→代理读回→ Range 206→伪造键 403)。
This commit is contained in:
@@ -27,7 +27,7 @@ feedback/
|
||||
├─ admin.php 管理后台(口令登录:审核 / 管理全部问题 / 站点设置 / 操作日志)
|
||||
├─ install.php 安装向导(数据库不存在时自动引导进来;装完建议删除)
|
||||
├─ upload.php 附件上传接口(两步:领对象键 → 收文件本体,local 落盘 / OSS 代理 PUT)
|
||||
├─ media.php 附件代理输出(私有桶 + 内网 Endpoint 下图片/视频的唯一对外读取通道,带鉴权与 Range)
|
||||
├─ media.php 附件代理输出(图片/视频的**唯一对外读取通道**:无论存本机还是 OSS,前台地址都是 media.php?k=…,带鉴权与 Range)
|
||||
├─ captcha.php "换一题"用的人机验证刷新接口(返回 JSON)
|
||||
├─ api.php 只读数据接口(需令牌),供自动化 / AI 读取
|
||||
├─ cron.php 附件过期清理 + 通知邮件补发(配计划任务)
|
||||
@@ -36,7 +36,7 @@ feedback/
|
||||
├─ lib/ 内部库(bootstrap / db / util / oss / attach / captcha / mailer / layout)
|
||||
├─ assets/ style.css / app.js / 图标(favicon、各尺寸 PNG、site.webmanifest)
|
||||
├─ data/ SQLite 数据库目录(已用 .htaccess 拒绝访问)
|
||||
├─ uploads/ 本机附件目录(仅"本机硬盘"模式下使用;PHP 按需自动创建)
|
||||
├─ uploads/ 本机附件目录(仅"本机硬盘"模式下使用;PHP 按需自动创建;**目录禁止 Web 直连,附件只走 media.php**)
|
||||
├─ .htaccess 禁止目录列表、禁止下载 .db/.md
|
||||
└─ README.md 本文件
|
||||
```
|
||||
@@ -275,14 +275,29 @@ php /www/wwwroot/你的域名/feedback/cron.php
|
||||
> `local/…` 一律按本机文件读,`fb/…`(或你配的 `oss.prefix`)一律按 OSS 读。
|
||||
> 所以中途从 OSS 换成硬盘(或反过来)时,**已经发过的帖子里的附件照常显示**。
|
||||
|
||||
> ★ **前台地址与存储方式无关(统一代理)**
|
||||
> 无论选「本机硬盘」还是「阿里云 OSS」,页面上的图片 / 视频地址**永远**是同一个形态:
|
||||
> ```
|
||||
> media.php?k=<对象键> 例:media.php?k=local%2F2026%2F09%2Fabcd.jpg
|
||||
> ```
|
||||
> 这样做有两个好处:
|
||||
> 1. **路径统一**:存储方式对页面与前端 JS 完全透明,换存储不用改前端、也不会出现两套 URL 逻辑;
|
||||
> 2. **不暴露真实地址**:本机模式下不会给出 `uploads/2026/09/xxxx.jpg` 这类可被猜目录、被批量抓取的直链;
|
||||
> OSS 模式下更不会出现任何 bucket / endpoint / 签名痕迹。
|
||||
> 真实的物理位置只由服务器在 `media.php` 内部按对象键前缀解析。
|
||||
> 数据库里**只存对象键**,地址是渲染时现算的 —— 所以这项改动对**历史附件也立即生效,无需迁移数据**。
|
||||
|
||||
**本机硬盘模式的两个注意点**
|
||||
|
||||
1. 目录由 PHP **按需自动创建**(`fb_local_writable()` 里的 `@mkdir`),属主就是 PHP 进程用户,天然可写。
|
||||
⚠️ **不要用 SFTP/部署账号手动建这个 `uploads/` 目录**——那样属主会变成部署账号,
|
||||
PHP 写不进去,上传会失败。后台「存储体检」会明确显示"可写 ✅ / 不可写 ❌"并给出处置办法;
|
||||
真遇到了,**删掉整个 `uploads/`(含 `.htaccess`)再刷新页面**,PHP 会重建。
|
||||
2. 目录里自动带一个 `.htaccess`:禁止列目录、禁止执行 `.php`/`.pl`/`.py`/`.cgi`/`.sh` 等脚本,
|
||||
只允许当静态图片 / 视频读取。对象键由服务端生成并做正则白名单校验,客户端无法指定路径。
|
||||
2. 目录里自动带一个 `.htaccess`:**整个目录一律拒绝 Web 直接访问**(附件只走 `media.php` 代理,
|
||||
真实路径不外泄),并额外禁止执行 `.php`/`.pl`/`.py`/`.cgi`/`.sh` 等脚本。
|
||||
该规则带**版本标记**(`# fb-local-guard: vN`),程序每次确保目录时比对版本,
|
||||
老站点上残留的旧版 `.htaccess` 会被**自动升级**,不需要手工替换。
|
||||
对象键由服务端生成并做正则白名单校验,客户端无法指定路径。
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user