关于Git鉴权你不得不知道的知识点

须弥零一

共 5761字,需浏览 12分钟

 · 2021-08-28

须弥零一

注意:由于微信的限制,本文中的超链接可能不会在文中显示,建议点击文末的 阅读原文 查阅。

关于Git鉴权你不得不知道的知识点

Git 作为一款目前广为流行的版本控制系统,想必大家都很熟悉了,这里不再过多的介绍,如果想系统的了解 Git 可以去 这里 在线阅读,或者 下载PDF 学习。

背景

用过 Git 的朋友都知道,不管我们使用的是 GitHubGitLabGitee还是其他公司自建的基于 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 的密钥一点关系都没有。简单的使用如下命令即可解决:

git config --global credential.helper store

根据我们自己的需要上面命令中 --global 不是必须的,另外 store 可以根据自己的需要修改为上面提到的四种之一,当然默认情况是不需要配置的。

设置参数和多工具配置

store 模式可以接受一个 --file <path> 参数,可以自定义存放密码的文件路径(默认是 ~/.git-credentials )。 cache 模式有 --timeout <seconds> 参数,可以设置后台进程的存活时间(默认是 “900”,也就是 15 分钟)。下面是一个配置 store 模式自定义路径的例子:

git config --global credential.helper 'store --file ~/.my-credentials'

Git 允许我们配置多个辅助工具。当查找特定服务器的凭证时,Git 会按顺序查询,并且在找到第一个应答时停止查询。当保存凭证时,Git 会将用户名和密码发送给所有配置列表中的辅助工具,它们会按自己的方式处理用户名和密码。如果你在闪存上有一个凭证文件,但又希望在该闪存被拔出的情况下使用内存缓存来保存用户名密码,.gitconfig 配置文件如下:

[credential]    helper = store --file /mnt/thumbdrive/.git-credentials    helper = cache --timeout 30000

这样的好处是,你可以把你的密码放在自己的U盘里。你自己用的时候插入U盘就可以不用输入密码,走的时候U盘带走就必须要输入密码才行,另外超过了过期时间缓存的密码也就自动删除了。

SSH方式连接

SSH 方式连接是我们最常见的连接方式,简单操作方法如下:

首先生成公私钥(sshkey)对。

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 文件的内容:

root@Ubuntu20:~/.ssh# cat /etc/ssh/ssh_config# This is the ssh client system-wide configuration file.  See# ssh_config(5) for more information.  This file provides defaults for# users, and the values can be changed in per-user configuration files# or on the command line.# Configuration data is parsed as follows:#  1. command line options#  2. user-specific file#  3. system-wide file# Any configuration value is only changed the first time it is set.# Thus, host-specific definitions should be at the beginning of the# configuration file, and defaults at the end.# Site-wide defaults for some commonly used options.  For a comprehensive# list of available options, their meanings and defaults, please see the# ssh_config(5) man page.Include /etc/ssh/ssh_config.d/*.confHost *#   ForwardAgent no#   ForwardX11 no#   ForwardX11Trusted yes#   PasswordAuthentication yes#   HostbasedAuthentication no#   GSSAPIAuthentication no#   GSSAPIDelegateCredentials no#   GSSAPIKeyExchange no#   GSSAPITrustDNS no#   BatchMode no#   CheckHostIP yes#   AddressFamily any#   ConnectTimeout 0#   StrictHostKeyChecking ask#   IdentityFile ~/.ssh/id_rsa#   IdentityFile ~/.ssh/id_dsa#   IdentityFile ~/.ssh/id_ecdsa#   IdentityFile ~/.ssh/id_ed25519#   Port 22#   Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc#   MACs hmac-md5,hmac-sha1,umac-64@openssh.com#   EscapeChar ~#   Tunnel no#   TunnelDevice any:any#   PermitLocalCommand no#   VisualHostKey no#   ProxyCommand ssh -q -W %h:%p gateway.example.com#   RekeyLimit 1G 1h    SendEnv LANG LC_*    HashKnownHosts yes    GSSAPIAuthentication yes

可以看到里面有很多默认的设置项,至于每一项是什么含义这里就不一一列出了,感兴趣的朋友请移步至 ssh_config(5) - Linux手册 查阅。

我们清楚了 Git 使用 SSH 方式连接仓库是和 SSH 客户端直接相关的,那么修改 SSH 相关参数之后,就应该能解决我们上面的问题。

Git配置多个SSH-Key

我们假设一个场景,我有多个git账号都要使用,比如:

一个 Gitee,用于公司内部的工作开发一个 GitHub,用于自己进行的一些开发活动

解决方法

生成一个公司用的SSH-Key

$ ssh-keygen -t rsa -C 'xxxxx@company.com' -f ~/.ssh/gitee_id_rsa

生成一个GitHub用的SSH-Key

$ ssh-keygen -t rsa -C 'xxxxx@126.com' -f ~/.ssh/github_id_rsa
在 ~/.ssh 目录下新建一个 config 文件,添加如下内容(其中 Host 和 HostName 填写 git 服务器的域名,IdentityFile 指定私钥的路径)


# giteeHost gitee.comHostName gitee.comPreferredAuthentications publickeyIdentityFile ~/.ssh/gitee_id_rsa# githubHost github.comHostName github.comPreferredAuthentications publickeyIdentityFile ~/.ssh/github_id_rsa

配置文件中的 PreferredAuthentications 是为了指定客户端身份验证方法的顺序,此选项的默认值是:"gssapi-with-mic, hostbased, publickey, keyboard-interactive, password"

用ssh命令分别测试

$ ssh -T git@gitee.com$ ssh -T git@github.com


以 Gitee 为例,成功的回显如下:

root@Ubuntu20:~# ssh -T git@gitee.comHi ! You've successfully authenticated, but GITEE.COM does not provide shell access.

上面的关键就在于 ~/.ssh/config 的配置。通过配置我们指定了访问不同 Host 所使用的密钥文件,这样就很方便的对不同的环境做出了区分。上面我们提到的问题也就迎刃而解了。

参考

Git 工具 - 凭证存储服务器上的 Git - 生成 SSH 公钥ssh_config(5) Linux手册Git配置多个SSH-Key

注意:由于微信的限制,本文中的超链接可能不会在文中显示,建议点击文末的 阅读原文 查阅。

---- END ----

欢迎关注我的公众号“须弥零一”,原创技术文章第一时间推送。


浏览 89
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报