关于Git鉴权你不得不知道的知识点
共 5761字,需浏览 12分钟
·
2021-08-28 17:57
注意:由于微信的限制,本文中的超链接可能不会在文中显示,建议点击文末的 阅读原文 查阅。
关于Git鉴权你不得不知道的知识点
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 的密钥一点关系都没有。简单的使用如下命令即可解决:
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/*.conf
Host *
# 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 指定私钥的路径)# gitee
Host gitee.com
HostName gitee.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/gitee_id_rsa
# github
Host github.com
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.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.com
Hi ! 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
注意:由于微信的限制,本文中的超链接可能不会在文中显示,建议点击文末的 阅读原文 查阅。
欢迎关注我的公众号“须弥零一”,原创技术文章第一时间推送。