代理认证失败源于Composer未处理HTTP Basic Auth,而是将含凭据的代理URL直接交由cURL;需检查环境变量与Composer全局配置一致性、密码URL编码、NTLM代理兼容性,并用curl -x验证。

代理认证失败不是 Composer 配错了,是它根本没把凭证传给代理
Composer 本身不处理 HTTP Basic Auth 的代理认证逻辑 —— 它只是把 HTTP_PROXY 或 HTTPS_PROXY 环境变量里的完整 URL(含 user:pass@)原样交给 cURL。如果代理返回 407 Proxy Authentication Required,说明:要么 URL 里漏了账号密码,要么代理服务压根不认这个凭据(比如 NTLM 代理),要么密码里含特殊字符没做 URL 编码。
-
HTTPS_PROXY=http://user:pass@127.0.0.1:7890是合法格式;但HTTPS_PROXY=https://...或HTTPS_PROXY=http://127.0.0.1:7890(无用户信息)都会导致 407 - 密码含
@、/、:等字符时,必须用urlencode处理,例如密码pa@ss/word要写成pa%40ss%2Fword - 企业常用 NTLM 代理(如微软 Forefront、Zscaler)不支持这种明文 Basic Auth,Composer 会直接失败,必须用
cntlm或px做中转层
改代理账号密码不能只改环境变量,要同步更新 Composer 配置
很多人只改了系统环境变量,却忘了 Composer 的全局配置里也存了一份代理地址。这两处不一致时,composer config -g http-proxy 的值会覆盖环境变量,造成“改了没用”的错觉。
- 查当前生效的代理配置:
composer config -g --list | grep -E "(http|https)-proxy",确认输出两行且格式正确 - 更新全局代理设置(含新密码):
composer config -g http-proxy "http://newuser:newpass%40encoded@127.0.0.1:8080" - 更新后务必清缓存:
composer clear-cache,否则旧连接池可能复用已失效的凭据 - 验证是否真正走代理:
composer global status应返回 OK,而不是卡住或报Connection refused
curl -x 是唯一能快速定位问题的命令
别依赖 composer diagnose —— 它只检查配置语法,不发真实请求。真正验证代理链是否通,得用底层工具模拟 Composer 行为。
- 用和 Composer 同一版本的 PHP/cURL 发起等效请求:
curl -x "http://user:pass@127.0.0.1:7890" -I https://packagist.org/packages.json - 如果返回
407,说明代理认证失败;返回502,说明代理自身异常;超时或 TLS 报错,则是代理协议或证书问题 - Windows 用户注意:
curl.exe可能调用系统 WinHTTP,行为和 PHP 的 libcurl 不同,建议用php -r "print file_get_contents('https://packagist.org/packages.json');"并设置stream_context_create模拟
GitHub 私有包 + 代理环境下容易连环失败
当 Composer 走代理下载 GitHub 私有仓库时,会先连 Packagist 元数据,再跳转到 GitHub API 或 Git 地址。如果代理对 api.github.com 或 github.com 做了额外拦截(比如过滤 User-Agent 或限速),就会在 Loading composer repositories 阶段卡死,错误日志里却看不到明显提示。
- 临时绕过代理只针对 GitHub:
git config --global url."https://oauth2:YOUR-TOKEN@github.com/".insteadOf "https://github.com/",让 Git 层直连 - 确保
github-oauth.github.com凭据已配置:composer config --global github-oauth.github.com YOUR-TOKEN,Token 必须带repo权限 - 若仍失败,抓包看实际请求目标:代理是否把
https://api.github.com/repositories/xxx错误转发到了 HTTP 端口?
curl -x 复现,再比对 PHP/cURL 版本与代理能力是否匹配,最后才动 Composer 配置。


















