Git 作为一款目前广为流行的版本控制系统,想必大家都很熟悉了,这里不再过多的介绍,如果想系统的了解 Git 可以去 这里 在线阅读,或者 下载PDF 学习。
背景
用过 Git 的朋友都知道,不管我们使用的是 GitHub、GitLab、Gitee还是其他公司自建的基于 Git 做版本控制的系统。当我们 clone 了一个仓库之后,配置完仓库密钥,后面在自己本地不管什么操作都会一路畅通无阻,再也不用每次都输入密码了。
是的!我也是这么一直使用了很多年,但这次真的不行了。不管我怎么配置密钥还是逃不脱每次都要输入密码的情况。于是分析之~
不一样的Git鉴权策略
经过查阅资料和验证,最终发现原来这一次使用的代码 clone 协议是 http!。这是怎么回事?
不知道大家在 clone 代码时有没有注意,类似 GitHub、Gitee、Gitlab 的代码仓库的地址有类似下面这个选项:
下面来分别说说这两种方式的差异。
非SSH方式连接
非SSH方式一般为 HTTP 或者 HTTPS,我们暂且认为它们是同一个,下面以 HTTP 为例来说明。
这与我们所熟悉的 SSH 方式连接远端不同,HTTP 的每一次连接都是需要用户名和密码的。这在使用双重认证的情况下会很麻烦,因为我们需要输入一个随机生成并且毫无规律的 token 作为密码。
这里,Git 拥有一个凭证系统来处理这个事情。下面有一些 Git 选项:
- 默认所有都不缓存。每一次连接都会询问用户名和密码。
cache
模式会将凭证存放在内存中一段时间。密码永远不会被存储在磁盘中,并且在15分钟后从内存中清除。stote
模式会将凭证用明文的形式存放在磁盘中,并且永不过期。这意味着除非我们修改了在 Git 服务器上的密码,否则我们永远不需要再次输入我们的凭证信息。这种方式的缺点是我们的密码是用明文的方式存在 home 目录下的。- 如果你使用的是 Mac,Git 还有一种 “osxkeychain” 模式,它会将凭证缓存到你系统用户的钥匙串中。 这种方式将凭证存放在磁盘中,并且永不过期,但是是被加密的,这种加密方式与存放 HTTPS 凭证以及 Safari 的自动填写是相同的。
- 如果你使用的是 Windows,你可以安装一个叫做 “Git Credential Manager for Windows” 的辅助工具。 这和上面说的 “osxkeychain” 十分类似,但是是使用 Windows Credential Store 来控制敏感信息。可以 点此 下载。
所以我上面遇到的问题就是因为我系统中的 Git 管理凭证使用的是默认的设置,所以无论如何我怎么去设置密钥都不起作用的原因。这个和 SSH 的密钥一点关系都没有。简单的使用如下命令即可解决:
1 | git config --global credential.helper store |
根据我们自己的需要上面命令中
--global
不是必须的,另外store
可以根据自己的需要修改为上面提到的四种之一,当然默认情况是不需要配置的。
设置参数和多工具配置
store
模式可以接受一个 --file <path>
参数,可以自定义存放密码的文件路径(默认是 ~/.git-credentials
)。 cache
模式有 --timeout <seconds>
参数,可以设置后台进程的存活时间(默认是 “900”,也就是 15 分钟)。 下面是一个配置 store
模式自定义路径的例子:
1 | git config --global credential.helper 'store --file ~/.my-credentials' |
Git 允许我们配置多个辅助工具。当查找特定服务器的凭证时,Git 会按顺序查询,并且在找到第一个应答时停止查询。 当保存凭证时,Git 会将用户名和密码发送给所有配置列表中的辅助工具,它们会按自己的方式处理用户名和密码。 如果你在闪存上有一个凭证文件,但又希望在该闪存被拔出的情况下使用内存缓存来保存用户名密码,.gitconfig
配置文件如下:
1 | [credential] |
这样的好处是,你可以把你的密码放在自己的U盘里。你自己用的时候插入U盘就可以不用输入密码,走的时候U盘带走就必须要输入密码才行,另外超过了过期时间缓存的密码也就自动删除了。
SSH方式连接
SSH 方式连接是我们最常见的连接方式,简单操作方法如下:
首先生成公私钥(sshkey)对。
1 | ssh-keygen -t rsa -C "xxxx@xxx.com" |
注意:这里的 xxxx@xxx.com 只是生成 sshkey 的名称,并不约束或要求具体命名为某个邮箱。
按照提示完成三次回车,即可生成 sshkey。生成文件在默认目录 ~/.ssh
中后缀为 .pub
的为公钥,另一个同名的文件是私钥。
最后复制公钥内容填写到自己所使用的 Git 管理系统中即可。这个也是大家所周知的过程。
既然上面这个过程大家都操作过,那么有个问题不知道您思考过没:假如我的密钥目录下有不止一对密钥,又或者我要同时用 GitHub 和 Gitee 应该怎么办呢?
SSH的配置
上面这个问题的答案是,其实到了这个阶段就已经和 Git 没关系了,它只是运行一下 SSH 而已,所以上面的任务就完全交给了 SSH 客户端自己。
和所有绝大多数的命令行程序一样,SSH 客户端在运行时也是有一堆默认参数的,SSH 获取参数配置的顺序如下:
- 命令行选项
- 用户的配置文件(~/.ssh/config)
- 系统范围的配置文件(/etc/ssh/ssh_config)
对于相同的配置设置,SSH 将使用第一个获取的值作为有效值。一般系统可能没有 ~/.ssh/config
文件,先来看看 /etc/ssh/ssh_config
文件的内容:
1 | root@Ubuntu20:~/.ssh# cat /etc/ssh/ssh_config |
可以看到里面有很多默认的设置项,至于每一项是什么含义这里就不一一列出了,感兴趣的朋友请移步至 ssh_config(5) - Linux手册 查阅。
我们清楚了 Git 使用 SSH 方式连接仓库是和 SSH 客户端直接相关的,那么修改 SSH 相关参数之后,就应该能解决我们上面的问题。
Git配置多个SSH-Key
我们假设一个场景,我有多个git账号都要使用,比如:
- 一个 Gitee,用于公司内部的工作开发
- 一个 GitHub,用于自己进行的一些开发活动
解决方法
- 生成一个公司用的SSH-Key
1 | ssh-keygen -t rsa -C 'xxxxx@company.com' -f ~/.ssh/gitee_id_rsa |
- 生成一个GitHub用的SSH-Key
1 | ssh-keygen -t rsa -C 'xxxxx@126.com' -f ~/.ssh/github_id_rsa |
- 在
~/.ssh
目录下新建一个config
文件,添加如下内容(其中 Host 和 HostName 填写 git 服务器的域名,IdentityFile 指定私钥的路径)
1 | # gitee |
配置文件中的 PreferredAuthentications 是为了指定客户端身份验证方法的顺序,此选项的默认值是: “gssapi-with-mic, hostbased, publickey, keyboard-interactive, password”
- 用ssh命令分别测试
1 | ssh -T git@gitee.com |
以 Gitee 为例,成功的回显如下:
1 | root@Ubuntu20:~# ssh -T git@gitee.com |
上面的关键就在于 ~/.ssh/config
的配置。通过配置我们指定了访问不同 Host 所使用的密钥文件,这样就很方便的对不同的环境做出了区分。上面我们提到的问题也就迎刃而解了。
参考
欢迎关注我的公众号 须弥零一,跟我一起学习IT知识。
如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !