禁用 packagist.org 必须在 repositories 数组中单独写 {"packagist.org": false},位置需在末尾;否则仍走官方源。禁用后所有依赖(含间接)必须存在于私有源,且需启用 gpg 签名、https 和客户端签名验证三重防护。

为什么禁用 packagist.org 后包还是从官方源安装
根本原因是没写对键名或没放对位置——"packagist.org": false 必须作为独立条目,直接放在 repositories 数组里,不能嵌套在其他对象中,也不能写成 "packagist" 或 "packagist: false"。
常见错误写法:
-
"repositories": [{"packagist": false}]→ Composer 当作一个空仓库,不触发禁用 -
"config": {"packagist": false}→ 完全无效,Composer 不识别该路径 -
"repositories": [{"type": "composer", "url": "https://..."}, {"packagist.org": false}]→ 顺序错:必须把{"packagist.org": false}放在数组末尾,否则前面的源可能被忽略
正确写法(项目级):
"repositories": [
{"type": "composer", "url": "https://packages.mycompany.com/"},
{"packagist.org": false}
]
禁用后依赖找不到的真正原因
不是配置失败,而是 Composer 彻底关闭了 fallback 行为:一旦 {"packagist.org": false} 生效,它就只查你 repositories 里明确列出的地址,不会自动探测、不会尝试拼写相似的包名、也不会递归检查嵌套依赖是否在别处存在。
这意味着:
- 所有直接
require的包,必须已在私有源中发布并索引 - 每个间接依赖(比如
monolog/monolog被symfony/http-kernelrequire)也必须出现在私有源的packages.json中 - 私有源若用 Satis 构建,需确保
satis.json的require-all或require列表覆盖完整,否则build后的元数据天然缺失
验证方式:运行 composer show monolog/monolog --all -vvv,看请求 URL 是否只指向你的私有地址,且返回状态码为 200。
安全配置下必须同步启用的三道防线
禁用默认源只是第一步,不等于安全。私有仓库服务端和客户端都必须主动加固,否则攻击者仍能通过篡改元数据、中间人劫持或凭证泄露突破。
必须同时满足:
- 服务端启用 GPG 签名:
php bin/satis build satis.json web/ --sign,生成带packages.json.asc的签名文件 - 服务端强制 HTTPS + 关闭目录浏览:Nginx 配置中移除
autoindex on,添加location / { try_files $uri =404; } - 客户端启用元数据验证:
composer config -g security.signature-verification true,且确认composer diagnose输出signature verification: OK
漏掉任意一项,packages.json 就可被篡改,Composer 会照单全收并安装恶意版本。
CI/CD 中认证配置最容易出错的点
COMPOSER_AUTH 是 CI 环境里最脆弱的一环:格式稍错就静默失效,且无明确报错提示。
典型陷阱:
- JSON 值含换行或多余空格 → Composer 解析失败,退回到无认证状态
- 键名大小写错误,如写成
Http-Basic或HTTP_BASIC→ 被忽略 - 在脚本里用字符串拼接生成 JSON → 引号转义遗漏,导致
password中的特殊字符破坏结构
推荐做法:
- 用
jq生成:echo '{"http-basic": {"packages.mycompany.com": {"username": "ci", "password": "'"$CI_TOKEN"'"}}}' | jq -c - 流水线第一步校验:
composer config --global --list | grep -q "http-basic" || (echo "MISSING AUTH CONFIG" >&2; exit 1) - 绝对禁止在
composer.json里注释掉凭证——Git 历史和 IDE 缓存都可能暴露它
真正上线前要确认的,从来不是“能不能连上”,而是“连上的那个包,是不是它声称的那个版本”。签名、HTTPS、认证,三者缺一不可,少一个,信任链就断在那一点上。











