背景
如果你在github上有两个账号,一个是公司的工作账号,另一个是个人的git账号,当使用同一台设备在两个账号下工作,一般都会需要给这两个github账号配置ssh公钥用来进行身份验证,从而正常push代码。不知道大家会不会有这样的疑惑,如果我之前本地已经存在了一对儿ssh密钥对(公钥和私钥)是直接使用这已经已经存在的密钥对,还是再生成一个呢,再或者有的人会删除重新生成。
为什么要配置ssh密钥
回答这个问题之前先思考密钥对是干嘛的,ssh密钥的作用是进行消息加密和身份验证,这种认证方式使用公钥和私钥对传输的信息进行非对称解密加密,发送信息的一方和接受信息的一方持有不同的密钥从而保证了通信的安全。使用git给github推送代码,其实就是用ssh和github服务器进行了一次通信,所以只要保证github上的公钥能够和本地私钥匹配就能完成身份认证,也就是在多个平台使用一个ssh密钥对是可以进行身份认证的。但是这么做会出现很大的问题--权限管理混乱。
github的权限认证
github的权限系统是和账户绑定的。用户使用ssh进行请求时(推送代码就是一个通信请求),github会首先用配置的公钥匹配请求中经过私钥签名的身份信息,这一步通过说明身份认证通过,接下来会对账号的权限进行认证,判断请求的操作是否有权限。而github的账号权限是和公钥绑定的,也就是通过与用户请求对应的公钥来确定用户账户从而管理权限的,如果多个账户使用了同一个ssh密钥对,就无法通过公钥准备识别出用户的账户信息,也就会造成权限混乱。所以这种情况下,强烈建议给不同的github账号配置不同的ssh密钥,防止权限管理混乱。
给两个github账号配置ssh密钥
这里以mac电脑为例(Windows只是生成命令不同,原理是相通的),假设工作的github账号为github-work,个人的是GitHub-personal。如果之前使用过ssh密钥对,在~/.ssh
目录下应该是存在之前生成过的ssh密钥对,而且他们的名字应该是id_rsa
或者是id_ed25519
。如果之前从来没有生成过ssh密钥,那么可以使用以下命令进行生成(mac电脑中已经集成了SSH工具)
arduino
//这里通过-f参数指定了生成密钥文件的名字,目的是区分不同账号和平台使用的密钥,推荐在生成密钥时给密钥命名这样便于管理
ssh-keygen -t rsa -b 4096 -C "你的邮箱地址" -f id_rsa_github_personal
//同理,我们为工作的github账号也生成一个密钥对
ssh-keygen -t rsa -b 4096 -C "你的邮箱地址" -f id_rsa_github_work
具体怎么样使用生成的密钥我相信大家都懂,这里不再赘述。重点是给生成的密钥在ssh的config文件进行配置,下面讲一下为什么要给密钥进行配置
ssh认证中私钥的选择
当我们使用ssh和github进行通信的时候,比如用ssh地址克隆某一个项目会经历以下过程
- 首先git会尝试使用ssh连接到github服务器进行身份和权限的认证
- 认证成功把远程的仓库的代码文件传输到本地,如果认证失败会看到下面的报错信息
arduino
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
在ssh进行认证的过程中,ssh会在本地选择一个合适的私钥,给认证过程中服务器发送来的一个随机数进行签名(这里涉及到ssh通信的原理)并将结果返回给服务器进行身份确认,如果用来签名的私钥和公钥可以匹配,那么身份认证就会成功。如果本地有多个密钥对,则会根据默认规则(按照密钥的默认命名,id_rsa,id_dsa,id_ecdsa等)寻找密钥对,如果我们指定了密钥的名字,就需要在ssh配置文件中指定在某个服务器下(如github,gitlab,gitee等)认证身份需要的私钥。
ssh中config文件的配置
SSH(Secure Shell)的配置文件
~/.ssh/config
是用户级别的一个文本文件,它允许用户为不同的远程主机或服务自定义连接参数。通过这个文件,你可以方便地管理多个服务器、设置默认选项、以及指定特定私钥用于不同主机的身份验证。
这段话的意思就是,使用config文件可以管理不同平台的ssh连接,包括指定目标服务器的连接端口,使用的私钥文件等
下面是一个config文件的内容示例:
bash
# SSH配置文件示例
# 通用配置项
Host * # 这里使用通配符*表示所有主机
User yourusername # 默认登录用户名
Port 22 # 默认端口
ServerAliveInterval 60 # 每60秒发送一次心跳包以保持连接活跃
Compression yes # 开启数据压缩
# 特定主机配置
# 工作服务器配置
Host github-work
HostName real.work.server.com
IdentityFile ~/.ssh/id_rsa_github_work # 使用特定的私钥文件进行身份验证
User work-username # 针对这台服务器使用的用户名可能与默认不同
Port 2222 # 如果服务器监听非标准的SSH端口,可以在此指定
# 个人GitHub账户配置
Host github-personal
HostName github.com
PreferredAuthentications publickey # 只使用公钥认证方式
IdentityFile ~/.ssh/id_rsa_github_personal # 对应个人GitHub账号的私钥文件
# 其他可选配置,例如跳转代理
Host via-jump-host
HostName target.host.example.com
ProxyJump jump-host.example.com # 通过跳板机访问目标主机
我们看一下github的ssh地址基本形式:git@github.com:username/repo-name.git
。这是一个ssh基本的地址结构,git是用户名,git@
后面的部分可以是实际的服务器域名(如 github.com
),也可以是你在SSH配置文件(~/.ssh/config
)中定义的Host别名。
Host文件的别名
一般来说,给某个平台进行ssh配置Host后面的别名都是平台的域名,比如Host github.com
或者Host gitlab.com
或者Host gitee.com
,如果给github平台的两个账号指定认证的私钥,Host别名一定不能都写成 Host github.com
,因为如果Host后面的别名相同,后面的同名配置就会覆盖前面相同名字的配置。从而导致github上所有账号的私钥都是一个Host配置中指定的私钥。
具体的配置修改
bash
# SSH配置示例
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_github_work
# 注意:这里默认给个人github账号指定配置名称为github.com
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_github_personal
由于给工作账号的Host配置指定了别名,所以每当从工作账号使用ssh地址克隆项目的时候,需要把地址中git@
后面的github.com
改为Host配置的别名。对应这里的修改就是改为git@github-work
给多个平台配置ssh密钥
通过刚才的分析,如果想要给多个平台配置ssh密钥,比如给gitee,和gitlab配置ssh密钥(假设每个平台一个账号),再给每个平台生成了对应的密钥对之后只需要在config文件制定对应的私钥即可。下面的示例简单展示了具体配置,仅供参考。
bash
# 配置gitee
Host gitee.com
HostName gitee.com
User git
IdentityFile ~/.ssh/id_rsa_gitee #这里使用你为gitee生成的私钥
# 给gitlab上的账号配置
Host gitlab.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_gitlab #gitlab认证使用的私钥
希望本文对你理解配置ssh有所帮助~欢迎在评论区留言交流。