Composer install 报“401 Unauthorized”是因为未在auth.json中正确配置GitLab Personal Access Token;需使用gitlab-token键、HTTPS仓库URL,并确保Token具备read_api和read_repository权限。

为什么 composer install 报 “401 Unauthorized” 访问私有 GitLab 仓库?
Composer 默认不携带认证凭据访问 GitLab 的私有项目(如 git@gitlab.example.com:user/repo.git 或 https://gitlab.example.com/user/repo.git),尤其当仓库启用了双因素或仅允许 Token 访问时,会直接返回 401 Unauthorized 或 Could not fetch https://gitlab.example.com/api/v4/projects/...。这不是 Composer 配置错误,而是缺少服务端身份凭证。
在 auth.json 中配置 GitLab OAuth Token 的正确方式
GitLab 不接受 GitHub 风格的 oauth-token 字段,必须使用 gitlab-token 键,并且值必须是 Personal Access Token(PAT),且该 Token 至少需具备 read_api 和 read_repository 权限(若含子模块或需要获取项目元数据,read_api 不可省略)。
- Token 必须在 GitLab 后台生成:Settings → Access Tokens → Create personal access token
-
auth.json文件应放在项目根目录或全局配置路径(COMPOSER_HOME/auth.json),优先级:项目级 > 全局级 - 域名必须与 GitLab 实例完全一致(含端口、协议),例如
gitlab.example.com:8080和gitlab.example.com被视为不同 host
{
"gitlab-token": {
"gitlab.example.com": "glpat-xxxxxxxxxxxxxxxxxxxx"
}
}
如何验证 Token 是否生效?
运行 composer diagnose 只能检查基础配置,不能验证 GitLab Token;真正有效的验证方式是触发一次实际的包拉取:
- 确保
composer.json中依赖项使用 HTTPS URL(推荐)或 SSH URL(此时 Token 无效,需走 SSH key) - 执行
composer clear-cache清除可能缓存的失败响应 - 运行
composer require vendor/package:dev-main --no-cache(强制跳过本地缓存,直连 GitLab API) - 若仍失败,用
composer -v install查看详细请求 URL 和响应头,确认是否携带了Private-Token请求头
注意:Composer 会自动将 gitlab-token 值注入到所有对匹配域名的 GitLab API 请求中,Header 名为 Private-Token,不是 Authorization: Bearer ...。
常见踩坑点:HTTPS vs SSH、Token 权限、子模块和镜像源
很多问题不是 Token 配错,而是上下文不匹配:
- 如果
composer.json里写的是git@gitlab.example.com:user/repo.git(SSH 协议),auth.json中的gitlab-token完全不会被使用——SSH 走的是密钥认证 - 子模块(submodules)由 Git 命令单独克隆,不受 Composer Token 控制;需额外配置
git config --global url."https://gitlab.example.com/".insteadOf "git@gitlab.example.com:" - 若使用了自定义 Packagist 镜像(如 Satis 或 Private Packagist),Token 仅用于 Composer 向 GitLab 获取源码,镜像服务自身也需独立配置 GitLab 访问权限
- GitLab CE/EE 版本差异可能导致 API 路径微调(如旧版用
/api/v3),但 Composer 2.2+ 已统一适配v4,无需手动降级
最常被忽略的是:Token 生效只影响 API 请求(如获取 composer.json、解析分支、下载 zip 包),不参与 Git clone 过程本身——后者仍依赖系统级 Git 配置。










