从GitHub CLI禁止用户名密码登录引发的思考与总结
背景
在本地CLI中push github代码时, 要求输入用户名密码, 但输入密码之后, 提示禁止使用密码登录.
- 根据提示配置了半天SSH免登, 结果发现并不生效, push时仍然让输入账号名密码.
- 后续根据提示, 在GitHub页面新申请了Token, 然后使用 用户名+Token 登录就可以了.
从而引发了诸多疑问与思考.
GitHub访问几种方式
方案1: SSH方式
配置方式
这种方式, 可以通过配置SSH免登即可.
如何支持不同Host采用不同SSHKey?
如果在本地, 既需要配置gitee的SSH免登, 又需要配置github的SSH免登, 有需要配置其他Host的SSH免登, 怎么能让不同的Host使用不同的公私钥对?
- 配置样例如下:
vim ~/.ssh/config
-- 为 git@gitee.com:/xxx ssh地址配置
Host gitee.com
HostName gitee.com
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_rsa
-- 为 git@github.com:xxx/xxx ssh地址配置
Host github.com
HostName github.com
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
-- 其他地址默认ssh地址配置
Host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
- 验证是否配置正确:
[davywalker@davywalkers-MacBook-Pro ~]$ ssh git@github.com
PTY allocation request failed on channel 1
Hi DavyJones2010! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.
方案2: HTTPS方式
配置方式
这种方式, 即背景中的案例, 必须通过 用户名+Token方式 登录, 即CLI中密码字段, 不要输入账号的密码, 而是输入Token
搜索了下, 从2021年8月13日开始, GitHub已经禁止了 用户名+密码方式 登录
From August 13, 2021,
GitHub is no longer accepting account passwords when authenticating Git operations.
You need to add a PAT (Personal Access Token) instead,
and you can follow the below method to add a PAT on your system.
GitHub密码存储位置
在使用SourceTree的时候, 由于repo使用的也是HTTPS, 因此也提示输入 用户名+密码, 由于密码方式被禁用, 因此后续再push这个repo, 会一直报禁止密码登录错误.
但也找不到修改/删除该密码的位置.
查了下资料, 不同的操作系统, 甚至同样操作系统的不同的版本, 存储方式都不同. 这里以 MacOS Monterey 12.3.1版本 为例:
davywalkerdeMacBook-Pro:~ davywalker$ git config credential.helper
osxkeychain
可以看出来是由keychain进行的管理, 在Mac的 Applications -> Utilties -> Keychain Access
- 可以看到SourceTree应用保存的GitHub Repo密码.
- 同时也可以看到IntelliJ IDEA保存的GitHub Repo密码, 通过显示repo密码发现, 这个密码字段其实就是签发给Intellij的 PAT(Personal Access Token)
总结
由于本地配置的remote repo是HTTPS方式, 因此通过配置SSH免登方式必然是无效的.
登录安全思考
为啥禁止CLI HTTPS方式通过用户名密码登录?
应该是担心密码泄露.
但会在哪种情况下泄露密码?
- 存储过程: 为了防止每次push都重复输入, git client应该把用户名密码存储到本机某个位置了.
- 传输过程: HTTPS中间人攻击, 发生概率就较小了
所以应该还是密码存储的风险.
通过页面登录, 有交互方式可以实现MFA, 但CLI方式无法进行交互从而实现MFA.
这样从而减弱了安全性.
为啥通过用户名+Token方式登录, 就支持呢
几种类型的Token
- 密码: 时间维度是永久有效, 不可召回. 权限范围是无限的(除非子账号). 可能是有规律的.
- SecretKey: 时间维度通常是永久有效(但支持设定长期), 可以召回. 权限范围是有限的. 通常是UUID等无规律的.
- RefreshToken: 时间维度是较长维度(例如可以60天), 可以召回. 权限范围是有限的. 通常是UUID等无规律的.
- AccessToken: 时间维度是较短维度(例如4个小时), 可以召回(但一般不召回, 通过召回RefreshToken实现). 权限范围是优先的. 通常是UUID等无规律的.
几种登录方式
- 方式1: 在网页端, 通常选择密码方式登录, 但需要开启MFA以加固安全. 以该方式作为安全性最强, 权限最大的方式.
- 方式2: 在服务端SDK里, 通常选择SecretKey方式. SecretKey如果泄露, 可以通过方式1登录, 然后撤销SecretKey的有效性, 重新签发新的SecretKey.
- 方式3: 在移动端SDK里, 通常会签发一个RefreshToken+AccessToken. 每次AccessToken过期之后, 重新通过RefreshToken调用API申请新的AccessToken.
因此在GitHub CLI方式登录, 其实就是从方式1(但不带MFA)降级到方案2, 一是限制权限范围, 二是可以随时撤销.
其他解决方案
- 也可以将remote repo切换成SSH方式, 并配置SSH免登实现.