必须禁用Web服务器目录列表并显式拦截敏感路径,因ThinkPHP无法控制静态文件访问;Apache需删Options Indexes并配置Require all denied,Nginx须设autoindex off及location ^~ /app/ { return 403; }等规则。

这不是 ThinkPHP 能防住的问题,而是 Web 服务器配置必须关掉的功能。目录列表浏览(Directory Listing)由 Apache 的 Options Indexes 或 Nginx 的 autoindex on 触发,和 PHP、ThinkPHP 入口文件、中间件、路由完全无关。
为什么 public/.htaccess 拦不住 app/ 和 config/ 目录
.htaccess 只对当前目录及其子目录生效,且仅在 Apache 启用 AllowOverride All 时才被读取。如果你把 Web 根目录设在项目根(比如 /var/www/myapp/),那么 app/、config/ 就和 public/ 并列,public/.htaccess 压根不会进入它们执行。
常见错误做法包括:
- 把整个 ThinkPHP 项目放 Web 根下,指望
public/.htaccess拦住上层目录 - 在
config/目录里放一个.htaccess,但没确认服务器是否启用AllowOverride - 用
deny from all写在项目根的.htaccess里,却忘了它对../config/这类路径无效
Nginx 下如何真正禁用目录列表
Nginx 不支持 .htaccess,必须改站点配置。关键点不是“隐藏”,而是“拒绝访问”:
立即学习“PHP免费学习笔记(深入)”;
- 全局关闭:确认配置中没有
autoindex on,有则改为autoindex off - 显式拦截敏感目录:
location ^~ /app/ { return 403; } - 同理加
location ^~ /config/ { return 403; }、location ^~ /runtime/ { return 403; } - 别漏掉
location ^~ /common/和location ^~ /extend/(如果存在)
注意 ^~ 是前缀匹配且优先级高于正则,比 location /app/ 更可靠;return 403 比 deny all 更明确,不依赖 allow/deny 指令顺序。
Apache 下必须删掉 Options Indexes
检查虚拟主机配置或项目根目录下的 .htaccess,删掉所有含 Options Indexes 的行。正确写法是:
-
Options -Indexes(减号表示禁用) - 或者更安全的:
Options None,再按需开启FollowSymLinks等必要项 - 对敏感目录单独加限制:
<Directory "/var/www/myapp/app"> Require all denied </Directory>
不要只在 public/ 里写 Options -Indexes——它对同级的 app/ 完全无效。
最易被忽略的一点:ThinkPHP 的 index.php 入口只处理能被路由识别的请求(如 /index.php/user/login),而直接 GET /config/database.php 是静态文件请求,压根不进 PHP,更不经过任何中间件或配置。验证方式很简单:curl -I http://yoursite.com/config/database.php,只要返回 200 就已泄露。



















