Composer没有htaccess-protect配置项,它不存在于官方schema、源码或文档中;真正防护vendor目录需将public/设为Web根目录,而非依赖任何Composer配置。

Composer 没有 htaccess-protect 这个配置项,设了也无效——它根本不存在于任何官方版本中。
为什么 htaccess-protect 不是 Composer 的配置
这个键名在 composer.json Schema、源码、2.5–2.9 所有稳定版文档里都查不到。它大概率来自过时的第三方插件(比如已废弃的 fxp/composer-asset-plugin)或对 Laravel 安装脚本的误读。Composer 本身不生成、不修改、也不读取 .htaccess 文件——那是 Apache 的事,和依赖管理无关。
常见错误现象:
- 在
composer.json里写了"htaccess-protect": true,运行composer install后毫无反应 - 部署后仍能通过浏览器直接访问
/vendor/autoload.php,误以为“配置没生效” - Apache error_log 报
Invalid command 'RewriteRule',其实是mod_rewrite没启用,跟 Composer 无关
真正该做的:把 public/ 设为 Web 根目录
vendor 目录暴露的根源从来不是“没开保护开关”,而是 Web 服务器根目录指向了项目根(含 vendor/、composer.json),而不是 public/ 子目录。
正确做法(以 Apache 为例):
使用tbot机器ID身份文件配合tsh CLI,通过Teleport访问控制SSH登录托管主机或执行远程命令。
- 确认虚拟主机配置中
DocumentRoot指向的是/var/www/myapp/public,不是/var/www/myapp - 确保
public/下只有index.php、静态资源等可公开文件,vendor/和src/必须在其上级目录 - 如果用 CI/CD,检查部署脚本有没有执行
cp -r vendor public/—— 这会直接绕过所有防护
错误做法:
- 把整个 Git 仓库克隆到
/var/www/myapp,再把DocumentRoot设为该路径 - 依赖
.htaccess拦截vendor/,却忘了AllowOverride All没开,规则压根不生效
Apache 下必须加的 .htaccess 排除规则(仅当无法改 DocumentRoot 时)
如果你暂时无法调整 Web 根目录(极少见),必须手动写 .htaccess 规则,且要放在最顶部、带 [L] 终止匹配:
RewriteRule ^vendor(/|$) - [L] RewriteRule ^(composer\.(json|lock)|phpunit\.xml) - [L,R=404]
注意点:
-
^vendor(/|$)比^vendor/更安全,覆盖/vendor和/vendor/autoload.php两种请求 - 必须加
[L],否则后续重写规则可能劫持请求,导致Class not found - Nginx 用户请用
location ^~ /vendor/ { return 403; },.htaccess对它完全无效
最容易被忽略的一环:CI/CD 流水线里的路径错位
绝大多数线上 /vendor/autoload.php 可直访问题,不是开发环境没配好,而是构建产物被错误地复制进了 Web 可达路径。比如:
- GitHub Actions 中用了
actions/checkout+composer install,但没指定working-directory: ./public - Dockerfile 里
COPY . /var/www后,又用apache2ctl -D FOREGROUND启动,默认 DocumentRoot 是/var/www - 宝塔/AMH 等面板一键部署时,选了“整站上传”,却没手动切换根目录到
public/
验证方法很简单:在服务器上运行 php -r "echo \$_SERVER['DOCUMENT_ROOT'];",再对比 ls -la \$_SERVER['DOCUMENT_ROOT']/../vendor —— 如果能列出内容,说明结构已经错了,这时候调 composer.json 里的任何字段都没用。

















