composer config http-basic 只生效一个仓库是因为重复执行会覆盖全局 auth.json 中同一域名的凭证,不同域名则共存;务必确保配置域名与请求 host 完全一致(如 pkg.example.com),推荐用 --auth 写入项目级 auth.json 或手动编辑。

composer config http-basic 为什么只生效一个仓库?
因为 composer config 默认写入全局配置(~/.composer/auth.json),而多个私有仓库的 http-basic 凭证必须按域名分别存储,不是覆盖写,是合并写。直接反复执行 composer config --global http-basic.repo-a.com user pass 会把前一个删掉——这是最常踩的坑。
- 每次调用
composer config写http-basic,实际是在更新auth.json的http-basic对象,键是域名,值是账号密码;重复写同一域名会覆盖,但不同域名会共存 - 务必确认你填的域名和
composer.json里仓库的url域名完全一致(比如pkg.example.com≠https://pkg.example.com,只认前者) - 如果仓库 URL 带路径(如
https://pkg.example.com/api/v1),凭证仍只认pkg.example.com这一级域名
怎么安全地添加多个私有仓库凭证?
别用 --global 反复覆盖,改用 --auth 显式写入项目级 auth.json,或手动编辑文件更可控。
- 推荐方式:在项目根目录运行
composer config --auth http-basic.pkg1.example.com username1 token1(不加--global),它会写进当前项目的auth.json,优先级高于全局 - 手动编辑更透明:打开项目下的
auth.json(没有就新建),按如下格式填:{ "http-basic": { "pkg1.example.com": { "username": "user1", "password": "token1" }, "pkg2.internal": { "username": "svc-composer", "password": "xxx" } } } - 敏感信息别硬编码进
composer.json或提交到 Git;auth.json默认被.gitignore忽略,但建议再确认下
使用 private packagist 或 Satis 时,http-basic 域名怎么对?
关键看 Composer 请求时发向哪个 Host。不是看仓库 url 的完整路径,而是看 HTTP 请求头里的 Host 字段。
- 例如仓库配置为
"url": "https://packages.mycompany.com",那凭证必须配给packages.mycompany.com - 如果用了反向代理(比如 Nginx 把
composer.mycompany.com转发到后端 Satis),凭证要配composer.mycompany.com,不是后端服务的真实域名 - 用
composer diagnose可看到 “Checking http-basic authentication”,它会列出当前已加载的域名凭证,用来快速核对是否识别成功
为什么加了凭证还是 401?常见链路排查点
401 不等于凭证没配,很可能是请求根本没带上认证头——Composer 只对匹配域名的请求才自动加 Authorization: Basic ...。
- 检查
composer config --list --auth输出里有没有对应域名,且结构正确(不能多一层嵌套,不能拼错字段名) - 用
composer -v install看详细日志,搜索Reading composer.json from和Downloading http://...行,确认请求的 URL 域名和你配的是否一致 - 私有仓库若强制要求 HTTPS,但你配的是 HTTP URL,Composer 会重定向,而重定向后的请求可能丢失认证头(尤其旧版 Composer);统一用 HTTPS 配置 URL 和凭证域名
- 某些 GitLab 私有包源需要
http-basic配gitlab.example.com,但实际拉取 ZIP 时走的是gitlab.example.com/api/v4/projects/...,域名仍算匹配,没问题










