您可以捐助,支持我们的公益事业。

金额: 1元 10元 50元

姓名:

邮件:

电话:

公司:

说明:

认证码: 验证码,看不清楚?请点击刷新验证码 必填



  要资料 文章 文库 Lib 视频 Code iProcess 课程 认证 咨询 工具 讲座吧   专家招募  
会员   
 
   
 
  
每天15篇文章
不仅获得谋生技能
更可以追随信仰
 
 
     
   
 订阅
  捐助
深入浅出Git权限校验
 
来源:网络 发布于 2017-4-17
来自于要资料   223 次浏览     评价:      
 

借助上次“掉坑”的经历,我对Git权限校验的两种方式重头进行了梳理,形成了这篇总结记录。

在本地计算机与GitHub(或GitLab)进行通信时,传输主要基于两种协议,HTTPS和SSH,对应的仓库地址就是HTTPS URLs和SSH URLs。

首先需要强调的是,HTTPS URLs和SSH 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:pass@github.com;下次再次访问仓库时就会自动读取~/.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_rsa和id_rsa.pub,通常无需修改,保持默认即可。不过,如果一台计算机中存在多个秘钥对,就需要修改秘钥文件名,名称没有强制的命名规范,便于自己辨识即可。

如下是创建秘钥对的过程。

? ssh-keygen -t rsa -b 4096 -C "mail@debugtalk.com"
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/Leo/.ssh/id_rsa): /Users/Leo/.ssh/debugtalk_id_rsa
Enter 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 mail@debugtalk.com
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 key和passphrase的情况下,才能通过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 git@github.com
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_rsa
Enter 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 git@github.com
Hi leolee! 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 git@github.com
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)? yes
Warning: Permanently added 'github.com,192.30.252.130' (RSA) to the list of known hosts.
Hi leolee! You've successfully authenticated, but GitHub does not provide shell access.

只有执行ssh-add -D或ssh-add -d pub_key命令,将私钥从ssh-agent删除后,认证信息才会失效。

? ssh-add -d ~/.ssh/id_rsa.pub
Identity removed: /Users/Leo/.ssh/id_rsa.pub (mail@debugtalk.com)
? ssh-add -l
The agent has no identities.
? ssh -T git@github.com
Permission denied (publickey).

同时使用多个GitHub账号

熟悉了HTTPS URLs和SSH URLs这两种校验方式之后,我们再来看之前遇到的问题。要想在一台计算机上同时使用多个GitHub账号访问不同的仓库,需要怎么做呢?

为了更好地演示,现假设有两个GitHub账号,debugtalk和leolee,在两个账号中各自有一个仓库,debugtalk/DroidMeter和DebugTalk/MobileStore(公司私有库)。

前面已经说过,HTTPS URLs和SSH 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 -l
4096 SHA256:lqujbjkWM1xxxxxxxxxxG6ERK6DNYj9tXExxxxxx8ew /Users/Leo/.ssh/debugtalk_id_rsa (RSA)
4096 SHA256:II2O9vZutdQr8xxxxxxxxxxD7EYvxxxxxxbynx2hHtg /Users/Leo/.ssh/id_rsa (RSA)

在详细讲解多账号共存的问题之前,我们先来回想下平时在Terminal中与GitHub仓库进行交互的场景。

?  DroidMeter git:(master) git pull
Already 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 push
Counting 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 git@debugtalk:debugtalk/DroidMeter.git
7df6839..68d085b master -> master

在操作过程中,本地计算机的ssh-agent与GitHub服务器建立了连接,并进行了账号权限校验。

当本地计算机只有一个GitHub账号时,这个行为并不难理解,系统应该会采用这个唯一的GitHub账号进行操作。那如果本地计算机中有多个Github账号时,系统是根据什么来判断应该选择哪个账号呢?

实际情况是,系统没法进行判断。系统只会有一个默认的账号,然后采用这个默认的账号去操作所有的代码仓库,当账号与仓库不匹配时,就会报权限校验失败的错误。

那要怎样才能让系统正确区分账号呢?这就需要我们手动进行配置,配置文件即是~/.ssh/config。

创建~/.ssh/config文件,在其中填写如下内容。

# debugtalk
Host debugtalk
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa
# DT
Host leolee
HostName github.com
User git
IdentityFile ~/.ssh/dt_id_rsa

要理解以上配置文件的含义并不难,我们可以对比看下两个项目的SSH URLs:

git@github.com:debugtalk/DroidMeter.git
git@github.com:DTSZ/Store_Android.git

其中,git是本地ssh-agent与GitHub服务器建立SSH连接采用的用户名(即User),github.com是GitHub服务器的主机(即HostName)。

可以看出,如果采用原始的SSH URLs,由于User和HostName都相同,本地计算机并不知道应该采用哪个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 git@debugtalk
Hi debugtalk! You have successfully authenticated, but GitHub does not provide shell access.
? ssh -T git@leolee
Hi leolee! 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 git@debugtalk:debugtalk/DroidMeter.git

在DebugTalk/MobileStore.git仓库中:

? git remote add origin git@leolee:DebugTalk/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://debugtalk@github.com/debugtalk/DroidMeter.git

在DebugTalk/MobileStore.git仓库中:

? git remote add origin https://leolee@github.com/DebugTalk/MobileStore.git

配置的原理也很容易理解,将GitHub用户名添加到仓库的Git地址中,这样在执行git命令的时候,系统就会采用指定的GitHub用户名去Keychain或~/.git-credentials中寻找对应的认证信息,账号使用错乱的问题也就不复存在了。

   
 订阅
  捐助
相关文章

每日构建解决方案
如何制定有效的配置管理流程
配置管理主要活动及实现方法
构建管理入门
相关文档

配置管理流程
配置管理白皮书
CM09_C配置管理标准
使用SVN进行版本控制
相关课程

配置管理实践
配置管理方法、工具与应用
多层次集成配置管理
产品发布管理
 

软件配置管理的问题、目的
软件配置管理规范
CQWeb 7.1性能测试与调优指南
为什么需要使用ClearCase
ClearCase与RTC的集成
利用ClearQuest 进行测试管理
更多...   

产品发布管理
配置管理方法、实践、工具
多层次集成配置管理
使用CC与CQ进行项目实践
CVS与配置管理
Subversion管理员

相关咨询服务
SCM启动咨询
SCM流程规范咨询
SCM评估性咨询

配置管理实践(从组织级到项目级)
通号院 配置管理规范与应用
配置管理日构建及持续集成
丹佛斯 ClearCase与配置管理
中国移动 软件配置管理
中国银行 软件配置管理
天津华翼蓝天科技 配置管理与Pvcs
 
 
 
 
 
每天2个文档/视频
扫描微信二维码订阅
订阅技术月刊
获得每月300个技术资源
 
 

关于我们 | 联系我们 | 京ICP备10020922号 京公海网安备110108001071号