深入浅出Git权限校验【转】

在本地计算机与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_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 [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_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 [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)? yes
Warning: 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.pub
Identity removed: /Users/Leo/.ssh/id_rsa.pub ([email protected])
? ssh-add -l
The 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 -l
4096 SHA256:lqujbjkWM1xxxxxxxxxxG6ERK6DNYj9tXExxxxxx8ew /Users/Leo/.ssh/dji_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 [email protected]: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

# DJI
Host 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中寻找对应的认证信息,账号使用错乱的问题也就不复存在了。

时间: 2024-10-25 16:01:16

深入浅出Git权限校验【转】的相关文章

后台权限校验拦截器

拦截器类 /* * 后台权限校验的拦截器 * *对没有登陆的用户,不可以进行访问 */ public class PrivilegeInterceptor extends MethodFilterInterceptor { @Override //执行拦截的方法 protected String doIntercept(ActionInvocation actionInvocation) throws Exception { //判断session中是否保存了后台用户的信息 AdminUser

gitolite实现git权限管理

环境要求 ssh $ sudo apt-get install ssh # 安装 $ sudo /etc/init.d/ssh start # 启动 $ sudo vi /etc/rc.local # 添加到开机启动 vsftpd $ sudo apt-get install vsftpd $ sudo /etc/init.d/vsftpd start $ sudo vi /etc/rc.local git $ sudo apt-get install git-core 权限配置 添加git用户

权限校验过滤器

-------------------siwuxie095 使用过滤器进行权限校验 一个简单的权限校验过滤器实例: 登录状态校验:如果没有成功登录就没有权限访问特定页面 当访问首页要进入 hello.jsp 页面时,首先判断是否处于登录状态: (1)如果是,直接点击进入 hello.jsp (2)如果否,则点击 hello.jsp 时进入 login.jsp,登录成功后自动跳转回 hello.jsp 工程结构目录如下: 后端代码: LoginServlet.java: package com.s

Apache shiro之权限校验流程

从张开涛blog学习后整理:http://jinnianshilongnian.iteye.com/blog/2018398 图片原图比较大,建议将图片在新的选项卡打开后100%大小浏览 在权限校验中RolePermissionResolver接口用于将角色所包含的权限全部解析出来(生成Permission实例)

前后端分离与权限校验

我在写web项目时,总是会为权限认证犯愁.在采用前后端分离后,后端只提供接口,项目的路由不再归后端管,而是由代理服务器(Nginx)控制.对于一般公开资源,URL的路由并不依赖于用户的状态,因此光靠代理服务器控制路由就够了.但是一旦涉及私密资源,事情就复杂起来了.对私密资源的访问需要进行权限校验,而这个校验一般由后端提供接口进行.但后端又不负责路由,即此时就做不到直接将不同状态的用户路由到不同资源.遇到这种状况时就需要 先调用后台接口后根据结果改变路由 . 显然,作为路由的发起者,不管是重定向还

类Shiro权限校验框架的设计和实现(2)--对复杂权限表达式的支持

前言: 我看了下shiro好像默认不支持复杂表达式的权限校验, 它需要开发者自己去做些功能扩展的工作. 针对这个问题, 同时也会为了弥补上一篇文章提到的支持复杂表示需求, 特地尝试写一下解决方法. 本文主要借助groovy脚本来实现复杂表达式的计算, 其思想是借鉴了Oval支持复杂表达式(groovy/javascript/ruby)的实现方式. 文章系列: 1. springmvc简单集成shiro  2. 类Shiro权限校验框架的设计和实现  3. 权限系统(RBAC)的数据模型设计 目标

Android 悬浮窗权限校验

原文:Android 悬浮窗权限校验 悬浮窗权限: <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> 权限检验和请求: //检查是否已经授予权限,大于6.0的系统适用,小于6.0系统默认打开,无需理会 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M&&!Settings.canDrawOverlays(

Azure DevOps Server:Git权限设置

Azure DevOps Server 权限概述 在Azure DevOps Server (之前名称为TFS)中,权限是一个比较复杂的概念.从权限层级上来说,包括服务器级别.团队项目集合级别.团队项目级别和对象级别. 其中的对象级别,是指对TFS系统中具体的每种类型的数据.或者每个具体的数据,对于不同的成员(或组)可以设置不同的权限. Git权限概述 对于Git库这个特定的数据对象,在Azure DevOps Server 中又分为代码库级别权限.库级别和分支级别的权限设置.就是说,可以针对不

python kafka权限校验client.id

kafka集群有权限校验,在连接时需要加入client.id.但pykafka不能配置该选项.搜索了一下,需要使用confluent-kafka 链接: https://blog.csdn.net/lanyang123456/article/details/80639625 #coding:utf-8 from confluent_kafka import Consumer, KafkaError mybroker = "127.0.0.1:9092" #host client_id