深入淺出Git許可權校正【轉】

來源:互聯網
上載者:User

標籤:

在本機電腦與GitHub(或GitLab)進行通訊時,傳輸主要基於兩種協議,HTTPSSSH,對應的倉庫地址就是HTTPS URLsSSH URLs

首先需要強調的是,HTTPS URLsSSH URLs對應的是兩套完全獨立的許可權校正方式,主要的區別就是HTTPS URLs採用帳號密碼進行校正,SSH URLs採用SSH秘鑰對進行校正。平時使用的時候我們可以根據實際情況,選擇一種即可。

HTTPS URLs

GitHub官方推薦採用HTTPS URLs的方式,因為該種方式適用面更廣(即使在有防火牆或代理的情況下也同樣適用),使用更方便(配置更簡單)。

採用HTTPS URLs地址clone/fetch/pull/push倉庫時,事先無需對本地系統進行任何配置,只需要輸入GitHub的帳號和密碼即可。不過如果每次都要手動輸入帳號密碼,也是一件很繁瑣的事情。

好在已經有多個機制可以讓操作不用這麼麻煩。

在Mac系統中,在啟用Keychain機制的情況下,首次輸入GitHub帳號密碼後,認證資訊就會自動儲存到系統的Keychain中,下次再次訪問倉庫時就會自動讀取Keychain中儲存的認證資訊。

在非Mac系統中,雖然沒有Keychain機制,但是Git提供了credential helper機制,可以將帳號密碼以cache的形式在記憶體中緩衝一段時間(預設15分鐘),或者以檔案的形式儲存起來(~/.git-credentials)。當然,Mac系統如果不啟用Keychain機制,也可以採用這種方式。

# cache credential in memory$ git config --global credential.helper cache# store credential in ~/.git-credential$ git config --global credential.helper store

credential.helper設定為store的情況下,首次輸入GitHub帳號密碼後,就會自動儲存到~/.git-credentials檔案中,儲存形式為https://user:[email protected];下次再次訪問倉庫時就會自動讀取~/.git-credentials中儲存的認證資訊。

另一個需要說明的情況是,如果在GitHub中開啟了2FA(two-factor authentication),那麼在本地系統中輸入GitHub帳號密碼時,不能輸入原始的密碼(即GitHub網站的登入密碼),而是需要事先在GitHub網站中建立一個Personal access token,後續在存取碼倉庫需要進行許可權校正的時候,採用access token作為密碼進行輸入。

SSH URLs

除了HTTPS URLs,還可以採用SSH URLs的方式訪問GitHub代碼倉庫。

採用SSH URLs方式之前,需要先在本機電腦中產生SSH keypair(秘鑰對,包括私密金鑰和公開金鑰)。預設情況下,產生的秘鑰位於$HOME/.ssh/目錄中,檔案名稱分別為id_rsaid_rsa.pub,通常無需修改,保持預設即可。不過,如果一台電腦中存在多個秘鑰對,就需要修改秘鑰檔案名稱,名稱沒有強制的命名規範,便於自己辨識即可。

如下是建立秘鑰對的過程。

? ssh-keygen -t rsa -b 4096 -C "[email protected]"Generating public/private rsa key pair.Enter file in which to save the key (/Users/Leo/.ssh/id_rsa): /Users/Leo/.ssh/debugtalk_id_rsaEnter passphrase (empty for no passphrase): <myPassphrase>Enter same passphrase again: <myPassphrase>Your identification has been saved in /Users/Leo/.ssh/debugtalk_id_rsa.Your public key has been saved in /Users/Leo/.ssh/debugtalk_id_rsa.pub.The key fingerprint is:SHA256:jCyEEKjlCU1klROnuBg+UH08GJ1u252rQMADdD9kYMo [email protected]The key‘s randomart image is:+---[RSA 4096]----+|+*BoBO+.         ||o=oO=**          ||++E.*+o.         ||+ooo +o+         ||.o. ..+oS. .     ||  .  o. . o      ||      .    .     ||       .  .      ||        ..       |+----[SHA256]-----+

在建立秘鑰的過程中,系統還建議建立一個名為passphrase的東西,這是用來幹嘛的呢?

首先,單獨採用密碼肯定是不夠安全的。如果密碼太簡單,那麼就很容易被暴力破解,如果密碼太複雜,那麼使用者就很難記憶,記錄到小本子裡面更不安全。

因此,SSH keys誕生了。SSH秘鑰對的可靠性非常高,被暴力破解的可能性基本沒有。不過,這要求使用者非常謹慎地保管好私密金鑰,如果別人使用你的電腦時偷偷地將你的私密金鑰拷走了,那麼就好比是別人拿到了你家裡的鑰匙,也能隨時開啟你家的門。

基於以上情況,解決辦法就是在SSH keys之外再增加一個密碼,即passphrase。只有同時具備SSH private keypassphrase的情況下,才能通過SSH的許可權校正,這就大大地增加了安全性。當然,這個passphrase也不是必須的,在建立秘鑰對時也可以不設定passphrase

另外,如果每次許可權校正時都要輸入passphrase,這也是挺麻煩的。好在我們不用再擔心這個問題,因為ssh-agent可以幫我們記住passphrase,Mac系統的Keychain也可以記住passphrase,這樣我們在同一台電腦中就不用重新輸入密碼了。

秘鑰對建立好以後,私密金鑰存放於本機電腦(~/.ssh/id_rsa),將公開金鑰(~/.ssh/id_rsa.pub)中的內容添加至GitHub賬戶。

# copy the contents of id_rsa.pub to the clipboard? pbcopy < ~/.ssh/id_rsa.pub# paste to GitHub# Login GitHub, 【Settings】->【SSH and GPG keys】->【New SSH Key】

不過,如果此時檢測本機電腦與GitHub的串連狀態,會發現系統仍提示許可權校正失敗。

? ssh -T [email protected]Permission denied (publickey).

這是因為在本機電腦與GitHub建立串連的時候,實際上是本機電腦的ssh-agent與GitHub伺服器進行通訊。雖然本機電腦有了私密金鑰,但是ssh-agent並不知道私密金鑰儲存在哪兒。因此,要想正常使用秘鑰對,需要先將私密金鑰加入到本機電腦的ssh-agent中(添加過程中需要輸入passphrase)。

# start ssh-agent in the background? eval "$(ssh-agent -s)"Agent pid 78370? ssh-add ~/.ssh/id_rsaEnter passphrase for /Users/Leo/.ssh/id_rsa: <myPassphrase>Identity added: /Users/Leo/.ssh/id_rsa (/Users/Leo/.ssh/id_rsa)

添加完成後,就可以查看到當前電腦中儲存的密鑰。

? ssh-add -l                4096 SHA256:xRg49AgTxxxxxxxx8q2SPPOfxxxxxxxxRlBY /Users/Leo/.ssh/id_rsa (RSA)

再次檢測本機電腦與GitHub的串連狀態,校正就正常通過了。

? ssh -T [email protected]Hi djileolee! You‘ve successfully authenticated, but GitHub does not provide shell access.

後續再進行clone/fetch/pull/push操作時,就可以正常訪問GitHub代碼倉庫了,並且也不需要再重新輸入帳號密碼。

而且,將私密金鑰加入ssh-agent後,即使刪除私密金鑰檔案,本機電腦仍可以正常訪問GitHub代碼倉庫。

? rm -rf ~/.ssh? ssh-add -l    4096 SHA256:xRg49AgTxxxxxxxx8q2SPPOfxxxxxxxxRlBY /Users/Leo/.ssh/id_rsa (RSA)? ssh -T [email protected]The authenticity of host ‘github.com (192.30.252.130)‘ can‘t be established.RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.Are you sure you want to continue connecting (yes/no)? yesWarning: Permanently added ‘github.com,192.30.252.130‘ (RSA) to the list of known hosts.Hi djileolee! You‘ve successfully authenticated, but GitHub does not provide shell access.

只有執行ssh-add -Dssh-add -d pub_key命令,將私密金鑰從ssh-agent刪除後,認證資訊才會失效。

? ssh-add -d ~/.ssh/id_rsa.pubIdentity removed: /Users/Leo/.ssh/id_rsa.pub ([email protected])? ssh-add -lThe agent has no identities.? ssh -T [email protected]Permission denied (publickey).
同時使用多個GitHub帳號

熟悉了HTTPS URLsSSH URLs這兩種校正方式之後,我們再來看之前遇到的問題。要想在一台電腦上同時使用多個GitHub帳號訪問不同的倉庫,需要怎麼做呢?

為了更好地示範,現假設有兩個GitHub帳號,debugtalkdjileolee,在兩個帳號中各自有一個倉庫,debugtalk/DroidMeterDJIXY/MobileStore(公司私人庫)。

前面已經說過,HTTPS URLsSSH URLs對應著兩套獨立的許可權校正方式,因此這兩套方式應該是都能單獨實現我們的需求的。

不過在詳細講解Git許可權校正的問題之前,我們先來回顧下Git設定檔的優先順序。

Git配置儲存位置及其優先順序

Unix-like系統中,儲存Git使用者資訊的主要有3個地方(Mac系統多一個Keychain):

  • /etc/gitconfig:儲存當前系統所有使用者的git配置資訊,使用帶有--system選項的git config時,配置資訊會寫入該檔案;
  • ~/.gitconfig~/.config/git/config:儲存目前使用者的git配置資訊,使用帶有--global選項的git config時,配置資訊會寫入該檔案;
  • Keychain Access:在開啟Keychain機制的情況下,進行許可權校正後會自動將帳號密碼儲存至Keychain Access
  • 倉庫的Git目錄中的config檔案(即repo/.git/config):儲存當前倉庫的git配置資訊,在倉庫中使用帶有--local選項的git config時,配置資訊會寫入該檔案;

在優先順序方面,以上4個配置項的優先順序從上往下依次上升,即repo/.git/config的優先順序最高,然後Keychain Access會覆蓋~/.gitconfig中的配置,~/.gitconfig會覆蓋/etc/gitconfig中的配置。

基於 SSH協議實現多帳號共存

先來看下如何採用SSH URLs實現我們的需求。

在處理多帳號共存問題之前,兩個帳號均已分別建立SSH秘鑰對,並且SSH-key均已加入本機電腦的ssh-agent

? ssh-add -l4096 SHA256:lqujbjkWM1xxxxxxxxxxG6ERK6DNYj9tXExxxxxx8ew /Users/Leo/.ssh/dji_id_rsa (RSA)4096 SHA256:II2O9vZutdQr8xxxxxxxxxxD7EYvxxxxxxbynx2hHtg /Users/Leo/.ssh/id_rsa (RSA)

在詳細講解多帳號共存的問題之前,我們先來回想下平時在Terminal中與GitHub倉庫進行互動的情境。

?  DroidMeter git:(master) git pullAlready up-to-date.?  DroidMeter git:(master) touch README.md?  DroidMeter git:(master) ? git add .?  DroidMeter git:(master) ? git commit -m "add README"?  DroidMeter git:(master) git pushCounting objects: 3, done.Delta compression using up to 4 threads.Compressing objects: 100% (2/2), done.Writing objects: 100% (3/3), 310 bytes | 0 bytes/s, done.Total 3 (delta 0), reused 0 (delta 0)To [email protected]:debugtalk/DroidMeter.git   7df6839..68d085b  master -> master

在操作過程中,本機電腦的ssh-agent與GitHub伺服器建立了串連,並進行了帳號許可權校正。

當本機電腦只有一個GitHub帳號時,這個行為並不難理解,系統應該會採用這個唯一的GitHub帳號進行操作。那如果本機電腦中有多個Github帳號時,系統是根據什麼來判斷應該選擇哪個帳號呢?

實際情況是,系統沒法進行判斷。系統只會有一個預設的帳號,然後採用這個預設的帳號去操作所有的代碼倉庫,當帳號與倉庫不匹配時,就會報許可權校正失敗的錯誤。

那要怎樣才能讓系統正確區分帳號呢?這就需要我們手動進行配置,設定檔即是~/.ssh/config

建立~/.ssh/config檔案,在其中填寫如下內容。

# debugtalkHost debugtalk    HostName github.com    User git    IdentityFile ~/.ssh/id_rsa# DJIHost djileolee    HostName github.com    User git    IdentityFile ~/.ssh/dji_id_rsa

要理解以上設定檔的含義並不難,我們可以對比看下兩個項目的SSH URLs

[email protected]:debugtalk/DroidMeter.git[email protected]:DJISZ/Store_Android.git

其中,git是本地ssh-agent與GitHub伺服器建立SSH串連採用的使用者名稱(即User),github.com是GitHub伺服器的主機(即HostName)。

可以看出,如果採用原始的SSH URLs,由於UserHostName都相同,本機電腦並不知道應該採用哪個SSH-key去建立串連。

因此,通過建立~/.ssh/config檔案,在Host中進行區分,然後經過CNAME映射到HostName,然後分別指向不同的SSH-key,即IdentityFile。由於HostName才是真正指定GitHub伺服器主機的欄位,因此這麼配置不會對本地ssh-agent串連GitHub主機產生影響,再加上Host別名指向了不同的SSH-key,從而實現了對兩個GitHub帳號的分離。

配置完畢後,兩個GitHub帳號就可以通過Host別名來進行區分了。後續再與GitHub伺服器進行通訊時,就可以採用Host別名代替原先的github.com。例如,測試本地ssh-agent與GitHub伺服器的連通性時,可採用如下方式:

? ssh -T [email protected]Hi debugtalk! You have successfully authenticated, but GitHub does not provide shell access.? ssh -T [email protected]Hi djileolee! You have successfully authenticated, but GitHub does not provide shell access.

可以看出,此時兩個帳號各司其職,不會再出現混淆的情況。

不過,我們還遺漏了很重要的一點。在本地代碼倉庫中執行push/pull/fetch等操作的時候,命令中並不會包含Host資訊,那系統怎麼知道我們要採用哪個GitHub帳號進行操作呢?

答案是,系統還是沒法判斷,需要我們進行配置指定。

顯然,不同的倉庫可能對應著不同的GitHub帳號,因此這個配置不能配置成全域的,而只能在各個項目中分別進行配置,即repo/.git/config檔案。

配置的方式如下:

debugtalk/DroidMeter倉庫中:

? git remote add origin [email protected]:debugtalk/DroidMeter.git

DJIXY/MobileStore.git倉庫中:

? git remote add origin [email protected]:DJIXY/MobileStore.git

配置的原理也很容易理解,就是將倉庫的Host更換為之前設定的別名。添加完畢後,後續再在兩個倉庫中執行任何git操作時,系統就可以選擇正確的SSH-key與GitHub伺服器進行互動了。

基於 HTTPS協議實現多帳號共存

再來看下如何採用HTTPS URLs實現我們的需求。

有了前面的經驗,我們的思路就清晰了許多。採用HTTPS URLs的方式進行Git許可權校正後,系統會將GitHub帳號密碼儲存到Keychain中(Mac系統),或者儲存到~/.git-credentials檔案中(Git credential helper)。

不管是儲存到哪裡,我們面臨的問題都是相同的,即如何在代碼倉庫中區分採用哪個GitHub帳號。

配置的方式其實也很簡單:

debugtalk/DroidMeter倉庫中:

? git remote add origin https://[email protected]/debugtalk/DroidMeter.git

DJIXY/MobileStore.git倉庫中:

? git remote add origin https://[email protected]/DJIXY/MobileStore.git

配置的原理也很容易理解,將GitHub使用者名稱添加到倉庫的Git地址中,這樣在執行git命令的時候,系統就會採用指定的GitHub使用者名稱去Keychain~/.git-credentials中尋找對應的認證資訊,帳號使用錯亂的問題也就不複存在了。

深入淺出Git許可權校正【轉】

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.