403 错误主因是 auth.json 未被 Composer 正确读取:位置错误(须在项目根目录或 ~/.composer/)、权限非 600、编码含 BOM、域名格式不符(如多写 https:// 或端口)、私有源 URL 缺尾部 /、token 权限不足或平台认证字段名不匹配。

403 不是权限不足,而是凭证根本没发出去——Composer 静默跳过错误 auth.json 后,用匿名身份访问私有源,自然被拒。
auth.json 放错位置或权限不对,直接导致 403
Composer 查找 auth.json 有固定路径顺序:先看项目根目录(和 composer.json 同级),再查 COMPOSER_HOME(Linux/macOS 是 ~/.composer/)。放错一层、进 src/ 或 vendor/ 就彻底失效。
- Linux/macOS 下必须运行
chmod 600 auth.json;权限不是600,Composer 会静默忽略文件,不报错也不提示 - 用
file -i ~/.composer/auth.json检查编码,必须是charset=utf-8;带 BOM 或us-ascii会导致解析失败 - 手动编辑时,
http-basic的 key 必须是纯域名(如"gitlab.example.com"),不能带https://、端口(除非非标准端口)、路径
Private Packagist / 自建 Satis 必须用 http-basic,且 URL 末尾带 /
type 为 composer 的私有源(如 Private Packagist、Satis)只认 http-basic 认证方式,且 url 必须以 / 结尾,否则拼出的 packages.json 路径 404,最终也表现为 403(服务端拒绝非法路径)。
-
repositories中写法必须是:{"type": "composer", "url": "https://repo.packagist.com/myorg/"}(注意末尾/) -
auth.json内容必须严格为:{"http-basic": {"repo.packagist.com": {"username": "your-api-token", "password": ""}}}(password字段留空字符串,不是null,也不能删掉) - Token 必须在后台绑定对应组织,并勾选
read权限;生成后仅显示一次,复制不全或含换行会导致认证失败
GitLab / GitHub / Bitbucket 的认证入口完全不同
不同平台的认证字段名、域名、token 类型互不兼容,写错一个就 403,且 Composer 不校验格式,直到请求发出才失败。
- GitLab HTTP 认证:用
http-basic,key 是gitlab.example.com(不含端口则不能加) - GitHub:必须用
github-oauth.github.com,命令是composer config --global github-oauth.github.com ghp_xxx;填api.github.com或www.github.com全部无效 - Bitbucket:Composer 2+ 只认
bitbucket-oauth.bitbucket.org;http-basic.bitbucket.org已废弃,手写无效 - 所有 token 必须由本人账号生成,App Password(Bitbucket)或 Personal Access Token(GitHub)需至少勾选
Repositories: Read
验证是否真生效,别信“我配过了”
靠肉眼检查配置容易漏掉隐藏问题。最可靠的方式是组合验证:
- 运行
composer diagnose:看到GitHub API: OK或HTTP Basic Authentication: OK才算通过 - 运行
composer config --global --list | grep -E "(http-basic|github-oauth|bitbucket-oauth)":输出非空且域名匹配才说明已注册 - 执行
composer show -a:列出所有已加载凭据,确认目标域名出现在其中 - 最后补一刀:
curl -v -u "token:" https://repo.packagist.com/myorg/packages.json(用户名填 token,密码留空),看是否返回 200 JSON
真正卡住的地方往往不是 token 本身,而是它压根没被读取——比如权限 600 漏了、auth.json 编码带 BOM、或者域名少写了端口却没在仓库 URL 里体现。这些细节不逐项核对,重装 Composer 或换网络都没用。


















