Composer报“401 Unauthorized”主因是私有仓库认证失败,非Composer自身鉴权问题;需检查auth.json配置、token权限、repositories中type与URL完整性,并用curl -I手动验证凭证有效性。

为什么composer install报“401 Unauthorized”却没提示具体包?
这不是 Composer 本身鉴权失败,而是它在访问某个 HTTPS 仓库(比如私有 GitLab、GitHub Packages 或自建 Satis)时,对方返回了 401 Unauthorized。常见于配置了 repositories 但漏掉认证凭据,或 token 过期/权限不足。
关键判断点:错误通常出现在 Loading composer repositories 阶段之后,且只影响特定源——比如成功拉取 packagist.org,但在读取 https://gitlab.example.com/api/v4/groups/mygroup/-/packages/composer 时中断。
- 运行
composer install -vvv,定位最后一条GET请求的 URL,确认是哪个源触发了 401 - 用
curl -I -H "Authorization: Bearer YOUR_TOKEN" https://your-private-repo/packages.json手动验证——若也返回 401,说明是凭证或权限问题,不是 Composer 配置问题 - 私有源若走 Basic Auth,用户名密码需 URL 编码;若含
@或/,不编码会导致解析失败
repositories 中 HTTPS 私有源怎么配 token?
不能只写 URL,必须显式声明 options 并注入认证头。Composer 不会自动读取 .netrc 或环境变量(除非你用 http-basic 类型并配 auth.json)。
推荐方式是项目级 auth.json(Git 忽略):
{
"http-basic": {
"gitlab.example.com": {
"username": "_",
"password": "glpat-xxxxxxxxxxxxxxxxxxxx"
}
},
"github-oauth": {
"github.com": "ghp_xxx..."
}
}
注意:http-basic 的 username 填 _ 是 GitHub/GitLab 的通用约定,password 填 Personal Access Token。
- Token 必须有
read_api(GitLab)或read:packages(GitHub)权限 - 配置后运行
composer clear-cache,否则旧失败响应可能被缓存 - 若用
composer config -g全局配 token,所有项目共享,不安全;仅限内网可信环境
报 401 却没走 auth.json?检查 type 和协议拼写
私有源的 type 必须匹配服务类型,否则 Composer 不触发对应认证逻辑。例如:
- GitLab Composer Repository →
"type": "composer",且 URL 必须以/packages.json结尾 - GitHub Packages →
"type": "composer",URL 格式为https://maven.pkg.github.com/OWNER/REPO(实际应为https://npm.pkg.github.com?错——PHP 包必须用https://nuget.pkg.github.com/OWNER?也不对——GitHub Packages for PHP 要求type: "composer"+ 正确域名 +auth.json中github.com条目 - 填错
https://gitlab.example.com/api/v4/groups/xxx/-/packages/composer却漏了末尾/packages.json,会 404 而非 401;补全后才可能触发认证
最易忽略的一点:repositories 中 URL 必须是完整 HTTPS 地址,不能省略 https:// —— 缺少协议头会导致 Composer 当作本地路径处理,后续请求直接失败。
企业网下 HTTPS 流量被中间设备重写导致 401
某些防火墙或代理会劫持 HTTPS 请求,替换证书并插入自己的 CA,再把请求转发给目标服务器。此时服务端看到的是“来自中间设备的请求”,而该设备没带任何 token,于是返回 401。
验证方法:
- 用浏览器打开私有源的
packages.jsonURL,看是否提示证书警告;若有,说明流量被中间设备干预 - 运行
openssl s_client -connect gitlab.example.com:443 -servername gitlab.example.com 2>/dev/null | openssl x509 -noout -issuer,检查 issuer 是否为你公司 CA - 临时绕过:把中间 CA 证书加到 PHP 的
curl.cainfo,或设COMPOSER_NO_SSL=1(仅调试)
真正修复得让运维把私有源域名加入白名单,或改用 IP 直连(配合 hosts 绑定)避免 TLS 劫持。











