本文介绍如何理解和设置 SSH 和 HTTPS 进行仓库认证。
Git 命令行操作有两种常用的认证方式 SSH 和 HTTPS。当Git 命令行操作因为仓库未授权而失败时,会看到如下错误输出:
remote: 找不到代码库,请确认是否有权限且代码库路径正确
致命错误:无法访问 'https://codeup.aliyun.com/...':The requested URL returned error: 403
或者
找不到代码库,请确认是否有权限且代码库路径正确
致命错误:无法读取远程仓库。
请确认您有正确的访问权限并且仓库存在。
在联系管理员解决授权问题之前,开发者先要确认认证时是否使用了正确的账号,即是否使用了预期的鉴权方式进行的认证?
Git 的认证方式 SSH 还是 HTTP
对于一个已经克隆的仓库,在仓库中执行 git fetch
或 git push
命令操作时,默认连接的远程服务器是当前分支跟踪的远程服务器,或者是由 origin 指定的远程服务器。
首先通过 git status
命令查看当前分支跟踪的远程分支:
$ git status
位于分支 master
您的分支与上游分支 'origin/master' 一致。
从命令输出我们可以看出当前分支 master
跟踪了上游的origin/master
分支。
那么origin
指向的服务器地址是什么?可以使用 git remote -v
或者如下命令查看:
$ git remote get-url origin
git@codeup.aliyun.com:my/example.git
从上面的示例输出我们可以看到仓库的 URL 地址,这个地址是一个 SSH 协议的仓库地址。对于 SSH 协议,仓库地址有两种表示方法:
带有 SSH 协议头的表示法,如:
ssh://gi*@codeup.aliyun.com:22/my/example.git
。其中,协议为:ssh
;服务器主机名为:codeup.aliyun.com
;主机端口:22
(可选);登录用户名:git
(可选)。URL 的最后部分为仓库路径,即:my/example.git
。采用 scp 命令的地址格式,即:
[user@]host:path
,如:gi*@codeup.aliyun.com:my/example.git
。其中,服务器主机名为:codeup.aliyun.com
;登录用户名:git
(可选)。冒号分隔符的右侧部分为仓库路径,即:my/example.git
。
对于 HTTPS 协议,仓库地址是标准的 URL 格式:https://[user]@host[:port]/path
。例如:https://codeup.aliyun.com/my/example.git
。其中,服务器主机名为:codeup.aliyun.com
;登录用户名如果省略,会在第一次登录时询问,或者认证助手(credential-helper)通过缓存自动提供用户名。URL 的最后部分为仓库路径,即:my/example.git
。
Git 的 SSH 认证方式
Git 的 SSH 认证使用公钥认证,即使用 ssh-keygen
命令生成 SSH 的公钥私钥文件,并将公钥文件上传到代码平台个人配置下,完成公钥认证。
SSH 支持通过主机别名的方式为 SSH 登录设定公私钥。方法是在当前用户的 ssh 配置文件中进行设置。例如:在 Linux、macOS 中 SSH 配置文件地址为:~/.ssh/config
。下面的示例是针对云效代码平台地址配置的一个别名my.aliyun
:
Host my.aliyun
User git
HostName codeup.aliyun.com
Port 22
IdentityFile /Users/my/.ssh/aliyun/id_rsa
上面的示例配置了一个主机别名 my.aliyun
。这个主机别名仅限本地使用,不会也不能用 DNS 进行查询。当用户使用 Git 克隆仓库 ssh://my.aliyun/my/example.git
时,实际连接的主机是:codeup.aliyun.com
;端口为:22
;用户为:git
;使用的SSH私钥为:/Users/my/.ssh/aliyun/id_rsa
。
那么有什么更加简便的方法来确认 SSH 协议下 Git 登录的用户账号是什么,以及认证使用了哪一个公私钥么?
例如对于上述地址ssh://my.aliyun/my/example.git
,我们使用 ssh 登录命令,可以看到认证是否成功,以及用户名:
$ ssh my.aliyun
Welcome to Codeup, gotgit!
Connection to codeup.aliyun.com closed.
从输出可以看到云效代码平台服务器不允许 SSH 登录,在显示登录账号为gotgit
之后服务器切断连接。
还可以在 SSH 连接命令中添加 -v
参数查看认证使用的公私钥,如下:
$ ssh -v gi*@codeup.aliyun.com
... ...
debug1: Offering public key: /Users/my/.ssh/aliyun/id_rsa RSA SHA256:8lEmVm11YzWZtT1U1FRrOx3rpMN1gFpOe776biyNkrI explicit
debug1: Server accepts key: /Users/my/.ssh/aliyun/id_rsa RSA SHA256:8lEmVm11YzWZtT1U1FRrOx3rpMN1gFpOe776biyNkrI explicit
Authenticated to codeup.aliyun.com ([118.118.31.XXX.XX) using "publickey".
... ...
在 Windows 操作系统,Git 的 SSH 认证使用的可能不是标准的 OpenSSH 命令,可通过环境变量 GIT_SSH_COMMAND
或者 Git 配置变量core.sshcommand
设置使用指定的 SSH 命令,可能是 plink.exe
或者tortoiseplink.exe
。验证登录的方式同上。
Git 的 HTTPS 认证方式
使用 HTTPS 协议访问远程 Git 仓库时,通常使用 HTTPS 协议的基本认证(Basic Authentication)。登录时使用用户在代码平台上的登录名,以及专门为 Git 认证申请的令牌(Token)。为了避免频繁输入用户名和令牌的繁琐,Git 提供了认证助手帮助缓存用户名和口令,因此通常只需要在第一次登录时输入用户名和令牌。
使用如下命令可以查看当前系统中所使用的认证助手:
$ git config credential.helper
store
示例中认证助手配置为store
,Git会使用内部命令git-credential-store
来缓存口令。Windows 上常用的认证助手为git-credential-wincred
。
如何确认当前 Git 的 HTTPS 认证使用哪一个用户名进行的登录?如果通过模拟 Git 和认证助手的交互获取认证使用的用户名会稍显麻烦。
一个简单的确认 Git HTTP 认证使用了指定用户名的方式是:将用户名编码在 URL 中(切忌不要将令牌编码在 URL中)。
例如:地址 https://got***@codeup.aliyun.com/my/example.git
中将用户名 gotgit
编码在 URL 地址中,就可以确认操作该仓库地址时使用的一定是指定的用户名。
如果想要修改一个已经克隆出来的本地仓库的地址,可以使用 git remote
命令。
查看 origin 标识的远程仓库地址,使用命令:
git remote get-url origin
修改 origin 标识的远程仓库地址,使用命令:
git remote set-url origin 。