關(guān)于Git鑒權(quán)你不得不知道的知識點
注意:由于微信的限制,本文中的超鏈接可能不會在文中顯示,建議點擊文末的 閱讀原文 查閱。
關(guān)于Git鑒權(quán)你不得不知道的知識點
Git 作為一款目前廣為流行的版本控制系統(tǒng),想必大家都很熟悉了,這里不再過多的介紹,如果想系統(tǒng)的了解 Git 可以去 這里 在線閱讀,或者 下載PDF 學習。
背景
用過 Git 的朋友都知道,不管我們使用的是 GitHub、GitLab、Gitee還是其他公司自建的基于 Git 做版本控制的系統(tǒng)。當我們 clone 了一個倉庫之后,配置完倉庫密鑰,后面在自己本地不管什么操作都會一路暢通無阻,再也不用每次都輸入密碼了。
是的!我也是這么一直使用了很多年,但這次真的不行了。不管我怎么配置密鑰還是逃不脫每次都要輸入密碼的情況。于是分析之~
不一樣的Git鑒權(quán)策略
經(jīng)過查閱資料和驗證,最終發(fā)現(xiàn)原來這一次使用的代碼 clone 協(xié)議是 http!。這是怎么回事?
不知道大家在 clone 代碼時有沒有注意,類似 GitHub、Gitee、Gitlab 的代碼倉庫的地址有類似下面這個選項:

下面來分別說說這兩種方式的差異。
非SSH方式連接
非SSH方式一般為 HTTP 或者 HTTPS,我們暫且認為它們是同一個,下面以 HTTP 為例來說明。
這與我們所熟悉的 SSH 方式連接遠端不同,HTTP 的每一次連接都是需要用戶名和密碼的。這在使用雙重認證的情況下會很麻煩,因為我們需要輸入一個隨機生成并且毫無規(guī)律的 token 作為密碼。
這里,Git 擁有一個憑證系統(tǒng)來處理這個事情。下面有一些 Git 選項:
?默認所有都不緩存。每一次連接都會詢問用戶名和密碼。?cache 模式會將憑證存放在內(nèi)存中一段時間。密碼永遠不會被存儲在磁盤中,并且在15分鐘后從內(nèi)存中清除。?stote 模式會將憑證用明文的形式存放在磁盤中,并且永不過期。這意味著除非我們修改了在 Git 服務(wù)器上的密碼,否則我們永遠不需要再次輸入我們的憑證信息。這種方式的缺點是我們的密碼是用明文的方式存在 home 目錄下的。?如果你使用的是 Mac,Git 還有一種 “osxkeychain” 模式,它會將憑證緩存到你系統(tǒng)用戶的鑰匙串中。這種方式將憑證存放在磁盤中,并且永不過期,但是是被加密的,這種加密方式與存放 HTTPS 憑證以及 Safari 的自動填寫是相同的。?如果你使用的是 Windows,你可以安裝一個叫做 “Git Credential Manager for Windows” 的輔助工具。這和上面說的 “osxkeychain” 十分類似,但是是使用 Windows Credential Store 來控制敏感信息。可以 點此 下載。
所以我上面遇到的問題就是因為我系統(tǒng)中的 Git 管理憑證使用的是默認的設(shè)置,所以無論如何我怎么去設(shè)置密鑰都不起作用的原因。這個和 SSH 的密鑰一點關(guān)系都沒有。簡單的使用如下命令即可解決:
git config --global credential.helper store根據(jù)我們自己的需要上面命令中
--global不是必須的,另外store可以根據(jù)自己的需要修改為上面提到的四種之一,當然默認情況是不需要配置的。
設(shè)置參數(shù)和多工具配置
store 模式可以接受一個 --file <path> 參數(shù),可以自定義存放密碼的文件路徑(默認是 ~/.git-credentials )。 cache 模式有 --timeout <seconds> 參數(shù),可以設(shè)置后臺進程的存活時間(默認是 “900”,也就是 15 分鐘)。下面是一個配置 store 模式自定義路徑的例子:
git config --global credential.helper 'store --file ~/.my-credentials'Git 允許我們配置多個輔助工具。當查找特定服務(wù)器的憑證時,Git 會按順序查詢,并且在找到第一個應(yīng)答時停止查詢。當保存憑證時,Git 會將用戶名和密碼發(fā)送給所有配置列表中的輔助工具,它們會按自己的方式處理用戶名和密碼。如果你在閃存上有一個憑證文件,但又希望在該閃存被拔出的情況下使用內(nèi)存緩存來保存用戶名密碼,.gitconfig 配置文件如下:
[credential]helper = store --file /mnt/thumbdrive/.git-credentialshelper = cache --timeout 30000
這樣的好處是,你可以把你的密碼放在自己的U盤里。你自己用的時候插入U盤就可以不用輸入密碼,走的時候U盤帶走就必須要輸入密碼才行,另外超過了過期時間緩存的密碼也就自動刪除了。
SSH方式連接
SSH 方式連接是我們最常見的連接方式,簡單操作方法如下:
首先生成公私鑰(sshkey)對。
ssh-keygen -t rsa -C "[email protected]"注意:這里的 [email protected] 只是生成 sshkey 的名稱,并不約束或要求具體命名為某個郵箱。
按照提示完成三次回車,即可生成 sshkey。生成文件在默認目錄 ~/.ssh 中后綴為 .pub 的為公鑰,另一個同名的文件是私鑰。

最后復制公鑰內(nèi)容填寫到自己所使用的 Git 管理系統(tǒng)中即可。這個也是大家所周知的過程。
既然上面這個過程大家都操作過,那么有個問題不知道您思考過沒:假如我的密鑰目錄下有不止一對密鑰,又或者我要同時用 GitHub 和 Gitee 應(yīng)該怎么辦呢?
SSH的配置
上面這個問題的答案是,其實到了這個階段就已經(jīng)和 Git 沒關(guān)系了,它只是運行一下 SSH 而已,所以上面的任務(wù)就完全交給了 SSH 客戶端自己。
和所有絕大多數(shù)的命令行程序一樣,SSH 客戶端在運行時也是有一堆默認參數(shù)的,SSH 獲取參數(shù)配置的順序如下:
?命令行選項?用戶的配置文件(~/.ssh/config)?系統(tǒng)范圍的配置文件(**/etc/ssh/ssh_config**)
對于相同的配置設(shè)置,SSH 將使用第一個獲取的值作為有效值。一般系統(tǒng)可能沒有 ~/.ssh/config 文件,先來看看 /etc/ssh/ssh_config 文件的內(nèi)容:
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,[email protected]# EscapeChar ~# Tunnel no# TunnelDevice any:any# PermitLocalCommand no# VisualHostKey no# ProxyCommand ssh -q -W %h:%p gateway.example.com# RekeyLimit 1G 1hSendEnv LANG LC_*HashKnownHosts yesGSSAPIAuthentication yes
可以看到里面有很多默認的設(shè)置項,至于每一項是什么含義這里就不一一列出了,感興趣的朋友請移步至 ssh_config(5) - Linux手冊 查閱。
我們清楚了 Git 使用 SSH 方式連接倉庫是和 SSH 客戶端直接相關(guān)的,那么修改 SSH 相關(guān)參數(shù)之后,就應(yīng)該能解決我們上面的問題。
Git配置多個SSH-Key
我們假設(shè)一個場景,我有多個git賬號都要使用,比如:
?一個 Gitee,用于公司內(nèi)部的工作開發(fā)?一個 GitHub,用于自己進行的一些開發(fā)活動
解決方法
?生成一個公司用的SSH-Key
$ ssh-keygen -t rsa -C '[email protected]' -f ~/.ssh/gitee_id_rsa?生成一個GitHub用的SSH-Key
$ ssh-keygen -t rsa -C '[email protected]' -f ~/.ssh/github_id_rsa~/.ssh 目錄下新建一個 config 文件,添加如下內(nèi)容(其中 Host 和 HostName 填寫 git 服務(wù)器的域名,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.
上面的關(guān)鍵就在于 ~/.ssh/config 的配置。通過配置我們指定了訪問不同 Host 所使用的密鑰文件,這樣就很方便的對不同的環(huán)境做出了區(qū)分。上面我們提到的問題也就迎刃而解了。
參考
?Git 工具 - 憑證存儲?服務(wù)器上的 Git - 生成 SSH 公鑰?ssh_config(5) Linux手冊?Git配置多個SSH-Key
注意:由于微信的限制,本文中的超鏈接可能不會在文中顯示,建議點擊文末的 閱讀原文 查閱。
歡迎關(guān)注我的公眾號“須彌零一”,原創(chuàng)技術(shù)文章第一時間推送。
