这不是 ThinkPHP 的问题,而是 Web 服务器配置不当导致目录列表暴露;需禁用 Apache 的 Options Indexes 或 Nginx 的 autoindex on,并将 Web 根目录设为 public/,严格禁止访问 app/、config/、runtime/ 等敏感目录。

ThinkPHP 项目根目录下出现 Apache/Nginx 默认目录列表怎么办
直接结论:这不是 ThinkPHP 的问题,而是 Web 服务器配置不当导致的。ThinkPHP 本身不控制目录是否可列,它只负责路由和逻辑;目录列表由 Apache 的 Options Indexes 或 Nginx 的 autoindex on 触发。
常见现象:访问 http://yourdomain.com/public/ 或 http://yourdomain.com/app/ 时看到文件列表(如 index.php、config.php 等裸露),尤其在开发环境随手放了测试文件后更危险。
- Apache 用户请检查虚拟主机或
.htaccess中是否含Options Indexes—— 必须删掉或改为Options -Indexes - Nginx 用户需确认站点配置里没有
autoindex on,如有,改为autoindex off - ThinkPHP 6+ 推荐把
public/设为 Web 根目录,其余目录(app/、config/、runtime/)必须**完全禁止 Web 访问** —— 这靠服务器配置实现,不是靠 .htaccess 隐藏
为什么 public/.htaccess 不能保护 app/ 和 config/ 目录
.htaccess 只对当前目录及子目录生效,且仅在 Apache 启用 AllowOverride All 时才被读取。如果你把 Web 根目录设在项目根(而非 public/),那么 app/ 和 config/ 就在根目录同级,.htaccess 压根不会进入这些目录执行。
- 错误做法:把整个 ThinkPHP 项目放 Web 根下,指望
public/.htaccess拦住上层目录 —— 它拦不住 - 正确做法:Web 根指向
public/,然后在服务器层面禁止访问../app、../config等路径(Nginx 用location ^~ /app/+return 403;Apache 用<directory></directory>+Require all denied) - 额外风险:
runtime/下的缓存、日志若被公开,可能泄露数据库账号、SQL 查询甚至 session 内容
ThinkPHP 自带的 index.php 入口能否防止敏感目录访问
不能。入口文件只接管「能被路由解析的请求」,比如 /index.php/user/login;但直接请求 /config/database.php 是静态文件访问,压根不经过 PHP,更不经过 ThinkPHP 路由和中间件。
立即学习“PHP免费学习笔记(深入)”;
- 验证方式:把
config/database.php文件权限设为 644,然后用 curl 直接 GET —— 如果返回 200 + 文件内容,说明已泄露 - ThinkPHP 5.1+ 在
public/index.php开头有define('APP_PATH', __DIR__ . '/../app/');,这只是定义路径常量,不产生任何访问控制 - 真正起作用的是:Web 服务器拒绝响应对非
public/子目录的 HTTP 请求 —— 这必须靠配置,不是靠代码
部署时最容易忽略的两个硬性检查点
很多线上事故不是因为不会配,而是上线前没做这俩动作:
- 手动访问一遍疑似敏感路径:
http://yoursite.com/runtime/、http://yoursite.com/config/、http://yoursite.com/app/—— 不要只测/public/,要测所有兄弟目录 - 检查
runtime/目录权限:Linux 下应为755(目录)+644(文件),且属主不是www-data或nginx用户(否则写入日志时可能被恶意覆盖)
目录浏览本身不等于被黑,但它等于把房间钥匙挂在门把手上——攻击者不需要猜,直接看。



















