
ThinkPHP 项目中,public 目录是唯一允许 Web 直接访问的入口,其余目录(如 app、config、runtime、vendor)**绝不能被 HTTP 请求读取**。一旦暴露,可能导致配置泄露、源码下载、.env 文件被获取等高危风险。
nginx 中禁止敏感目录被 Web 访问
最直接有效的控制方式是在 Nginx 配置里用 location 显式拒绝请求。这是生产环境必须加的防护层,仅靠目录权限不够。
location ~ ^/(app|config|database|extend|runtime|vendor)/ 是标准写法,匹配以这些路径开头的任何 URL必须放在 server 块内,且优先级高于通用 PHP 处理规则(建议放在 location ~ \.php$ 之前)搭配 deny all; 后,Nginx 会直接返回 403,不交由 PHP 处理注意:不要漏掉 database(有些项目把数据库迁移文件放这里)和 extend(第三方扩展若含配置也可能敏感)
Apache 的 .htaccess 对应防护
如果用 Apache,public/.htaccess 本身只管 public 下的重写,真正防目录遍历得靠上层配置或额外规则。
在项目根目录(非 public)添加 .htaccess 并写入:RewriteEngine On<br>RewriteRule ^(app|config|runtime|vendor|database|extend)/ – [F,L]若无法修改根目录配置,至少确保 public/.htaccess 中有 Options -Indexes,禁用目录列表Apache 2.4+ 推荐用 <Directory> 块配合 Require all denied,比 .htaccess 更可靠
上传目录的执行权限必须关闭
用户上传的文件(比如 public/storage)可读可写,但**绝对不能被执行**。否则上传一个 shell.php 就等于沦陷。
立即学习“PHP免费学习笔记(深入)”;
Nginx 中对上传目录加独立 location,并显式禁用 PHP 解析:location ^~ /storage/ { deny all; } 或更细粒度:location ~* ^/storage/.*\.(php|phar|phtml)$ { return 403; }Linux 下用 chmod -R a-x public/storage 移除所有执行位(不影响读写)确认 PHP 的 open_basedir 不包含上传目录,避免绕过
静态资源缓存与路径收敛
限制访问不只是“封”,还要“导”——让合法静态资源走正确路径,减少意外暴露可能。
所有 CSS/JS/图片必须放在 public/ 下的子目录(如 public/static/、public/uploads/),禁止放在 app/ 或 runtime/ 里Nginx 中为静态资源加缓存头:location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control "public, immutable"; }避免在模板里拼接非 public 路径,例如 <img src="{{ asset(‘runtime/images/logo.png’) }}"> 是错的,runtime 不该被 Web 访问
最容易被忽略的是:开发者常以为「只要目录权限设成 644 就安全了」,但 Web 服务器进程(如 www-data)若能读取 config/,而 Nginx 又没配 deny,那 https://site.com/config/database.php 仍可能直接下载源码。权限控制和 Web 层访问控制必须双管齐下。

评论(0)