ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

GitHub代码上传认证全攻略:SSH与Token原理与排障

GitHub代码上传认证全攻略:SSH与Token原理与排障 我第一次往 GitHub 上推代码的时候卡了整整一个下午。项目写好了git init跑了commit也做了结果倒在最后一步——git push。弹窗让我输账号密码输完告诉我认证失败换成 SSH 又说 Permission denied最后误打误撞用了 Token 方式推上去了结果第二天再 push 又提示 token expired。当时我一度以为 GitHub 在针对我。后来把 SSH 和 Token 两条路从头到尾都走了一遍才明白每个报错背后都是一个非常具体的原因而且绝大多数坑踩过一次之后基本不会再踩第二次。这篇文章不打算写成那种复制粘贴就能用的流水账教程我会把两种上传方式各自的原理、操作链路、常见报错的完整排查思路都讲清楚适合刚接触 Git 和 GitHub 的开发者也适合那些已经会 push 但每次遇到认证问题都要现搜解决方案的人。看完你应该能彻底理解为什么要用 SSH、为什么要用 Token、什么时候选哪个以及遇到报错时怎么一步步定位问题。1. SSH 与 Token先弄懂 GitHub 认证的底层差异1.1 为什么密码认证已经被 GitHub 废弃很多人第一次用 GitHub 时会觉得很奇怪为什么git push的时候输入账号密码总是失败原因很简单——GitHub 在 2021 年 8 月 13 日正式停止了对账户密码的 Git 操作认证支持。这不是临时策略而是永久性的变更。所以你在网上搜到的老教程里写输入 GitHub 账号和密码就能 push那些内容已经过时了照着做必然会踩坑。GitHub 官方给出的替代方案就是今天要讲的两种方式基于 SSH 密钥的认证以及基于 Personal Access Token个人访问令牌的 HTTPS 认证。理解这两种方式的底层逻辑比死记命令重要得多。因为只有理解了原理你才能在任何一台新电脑上快速配置而不是永远靠复制粘贴别人的命令碰运气。1.2 SSH 的公私钥模型和日常类比SSH 认证的核心是非对称加密。你会在本地生成一对密钥一个公钥、一个私钥。公钥可以理解为一把锁你把它放到 GitHub 服务器上私钥是唯一能打开这把锁的钥匙必须好好保存在你自己的电脑里。每次通过 SSH 连接 GitHub 时服务器会发送一个随机挑战你的电脑用私钥对它进行签名GitHub 用你预先上传的公钥来验证签名。验证通过就确认确实是本人连接建立成功。整个过程不需要传输密码私钥永远不会离开你的电脑。生活里最常见的类比就是门锁和钥匙公钥就是锁芯任何人往 GitHub 上挂一把锁都不怕被拿走锁本身不泄露任何敏感信息私钥是钥匙钥匙丢了别人就能进你家门所以私钥文件一定要保护好。SSH 密钥里还有一个可选的 passphrase口令短语相当于给钥匙再加一道保险即使私钥文件被别人拷走了没有 passphrase 也解不开。1.3 Token 的设计思路和常见误区Token 的思路和 SSH 完全不同。Token 本质上是一串具有特定权限的授权字符串它有点像是你住酒店时前台给的那张房卡——只能打开你被允许进入的房间对应仓库并且通常有一个有效期可以随时作废。你在 GitHub 后台生成 Token 时需要勾选它拥有哪些权限比如读写仓库、删除仓库、操作 workflow 等。这样做的好处是权限最小化某个 Token 泄露了只要去后台把那个 Token 删掉其他 Token 不受影响你的账号密码也不会暴露。很多人对 Token 有两个误区第一以为 Token 就是密码。不是的Token 在使用时是作为密码字段输入的但它不是账号密码它拥有独立的权限范围和生命周期。第二以为 Token 配置一次就一劳永逸。Token 会过期过期后需要重新生成并更新配置Git 凭据管理器里的记录也要更新这是它和 SSH 密钥在使用体验上最大的区别。2. 本地环境准备Git 安装、身份配置与仓库初始化2.1 三个平台安装 Git 的关键点系统里还没有 Git 的话先把环境搭好。Windows 用户直接去 git-scm.com 下载安装包一路 Next 就行。安装过程中有两个选项稍微留意一下选择默认编辑器默认是 Vim不熟悉 Vim 的可以改成 VS Code 或者 Notepad不然以后写 commit message 时误入 Vim 会一脸懵。调整 PATH 环境变量选默认的Git from the command line and also from 3rd-party software就好这样 Git 可以在 CMD、PowerShell、Git Bash 里都能用。macOS 用户最简单的方式是brew install gitLinux 用户根据发行版用apt install git或者yum install git。装完用一个命令验证git --version能输出版本号就说明安装成功了。Windows 上安装完 Git 之后强烈建议用Git Bash来执行本教程里的命令而不是用原生的 CMD 或 PowerShell。原因很简单Git Bash 模拟了 Linux 环境ls、cat、pbcopy之类的命令行为和我们平时看过的绝大多数教程一致踩坑概率小很多。2.2 全局身份配置与常见疑问Git 安装好之后第一步是配置你的身份信息否则 commit 的时候 Git 不知道你是谁git config --global user.name 你的名字 git config --global user.email 你的邮箱这里的邮箱建议和 GitHub 账号上绑定的邮箱保持一致。如果不一致你的 commit 在 GitHub 上可能不会关联到你的账号提交列表里显示的是灰色匿名头像。很多人忽略这个小细节结果提交了一堆代码GitHub 贡献图上却什么都没有。配置完成可以用git config --list查看当前所有配置。这里有个容易弄混的点这个user.name和user.email是 Git 提交时用于记录作者信息的和 GitHub 登录账号、和后面要讲的 SSH key 没有直接关系。2.3 GitHub 上新建仓库注意三个坑登录 GitHub 后点击右上角的 New repository填写仓库名选择 Public公开或 Private私有。这里有一个新手非常容易踩的坑如果你的本地项目已经存在不要在创建仓库时勾选 Add a README file、Add .gitignore 或 Choose a license。为什么因为一旦勾选GitHub 会在远端仓库里生成一个初始化的 commit。本地项目此时也有自己的 commit两边都有代码但历史不关联接下来 push 时 Git 会拒绝合并提示远端包含你本地没有的工作然后你就得先git pull --rebase origin main再 push。对新手来说这又是一道坎。最简单粗暴的办法本地项目已经有了就创建一个纯空白仓库一个文件都不要勾创建完直接把地址复制下来就行。如果远端仓库不小心勾了 README解决办法也不复杂git pull --rebase origin main git push -u origin main--rebase会把你的本地提交变基到远端提交之上让历史保持线性看起来比较清晰。3. SSH 上传密钥生成到 push 成功的完整链路3.1 生成密钥ed25519 优于 rsa 的理由SSH 方式的完整链路第一步是在本地生成一对密钥。打开 Git Bash 或终端执行ssh-keygen -t ed25519 -C 你的邮箱参数解释一下-t指定密钥类型ed25519是目前推荐使用的算法比传统的 RSA 更安全、密钥更短、生成速度也更快。GitHub 官方文档也是推荐使用 ed25519。只有当你需要连接一些老旧的服务器比如某些还不支持 ed25519 的 Linux 机器时才考虑用ssh-keygen -t rsa -b 4096生成 RSA 密钥。执行过程中会让你选择密钥保存位置默认是~/.ssh/id_ed25519直接回车即可。接着会提示输入 passphrase这相当于给私钥加一层保护口令可以留空直接回车。从安全角度建议设置一个但从使用便捷角度很多个人开发机器为了方便会留空。我个人的建议是个人电脑上日常开发可以留空公司电脑或多人共用的机器上务必设置 passphrase。密钥生成后~/.ssh目录下会出现两个文件id_ed25519私钥绝对不能泄露也不能提交到任何代码仓库。id_ed25519.pub公钥可以放心上传到 GitHub。3.2 将公钥注册到 GitHub先查看公钥内容cat ~/.ssh/id_ed25519.pub输出是一长串以ssh-ed25519开头、以你的邮箱结尾的字符串。复制它然后去 GitHub 页面右上角头像 → Settings → SSH and GPG keys → New SSH key。Title 随便填一个方便自己识别的名字比如 My MacBook ProKey 区域粘贴刚才复制的公钥最后点击 Add SSH key 即可。如果用的是 Windows Git Bash复制公钥更方便的方式是clip ~/.ssh/id_ed25519.pub3.3 Windows 用户最常踩的 config 权限坑公钥注册完之后先做一个连接测试ssh -T gitgithub.com第一次执行会提示确认主机的指纹输入yes回车。如果看到类似这样的输出说明 SSH 认证链路已经通了Hi 你的用户名! Youve successfully authenticated, but GitHub does not provide shell access.但很多 Windows 用户在这一步会遇到一个极其折磨人的报错Bad owner or permissions on C:\Users\xxx/.ssh/config这个报错的意思是你~/.ssh目录下的config文件权限配置不正确。Windows 的 OpenSSH 对配置文件有严格的权限要求config 文件只能由当前用户完全控制不能有其他账户的访问权限。这个坑通常出现在你从别的电脑拷贝 config 文件过来、或者用 Git 从仓库里同步了 config 文件的情况下——文件的属主和权限继承了原来的使用者Windows 检查时就不认账了。解决方法有两个方式一如果 config 文件里没有重要内容直接删掉或重命名问题立刻解决。很多人根本不需要配置文件里面顶多有一两行残留删了不影响使用。方式二如果 config 里确实有多个平台的主机配置需要手动修复权限右键点击 config 文件 → 属性 → 安全 → 高级 → 点击禁用继承 → 在弹出的窗口选择将已继承的权限转换为此对象的显式权限 → 然后逐个删除除了当前用户以外的所有条目 → 确定。完成后当前用户应该拥有完全控制权限重新执行ssh -T gitgithub.com验证即可。3.4 关联远程仓库并完成首次 pushSSH 测试通过后剩下的就是常规 Git 操作了。进入本地项目目录关联远程仓库git remote add origin gitgithub.com:你的用户名/你的仓库名.git注意这里的地址用的是 SSH 格式以gitgithub.com:开头而不是https://github.com/。你可以在 GitHub 仓库页面的 Code 按钮下拉菜单里切换到 SSH 标签直接复制对应地址。接下来把本地代码推上去git add . git commit -m Initial commit git branch -M main git push -u origin maingit branch -M main是把当前分支重命名为main因为 GitHub 默认主分支叫main而不是master这一步能避免分支名不一致带来的困惑。-u参数把本地分支和远程分支建立关联以后直接git push就能推送。首次 push 之后SSH 方式的好处就体现出来了以后每次git push都不需要再输入任何账号密码或令牌体验和无密码一样顺滑。4. Token 上传Personal Access Token 的创建与使用4.1 Token 的创建步骤与 scope 选择Token 方式的完整链路第一步是在 GitHub 后台生成一个 Personal Access Token。路径是GitHub 右上角头像 → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token。GitHub 目前提供两种 TokenTokens (classic)和Fine-grained personal access tokens。Classic 是传统方式权限粒度相对粗Fine-grained 是后来推出的新版本可以精确到某个仓库、某种操作还可以设置更灵活的有效期。对普通个人项目来说用 classic 就够了。创建时需要填写这些字段字段说明建议NoteToken 的名称备注写清楚用途比如 my-laptopExpiration有效期建议 30 天到 90 天尽量短Select scopes权限范围至少勾选repo完全控制私有仓库如果你的项目仓库是 Public 且只需要拉代码clone其实不需要任何 scope如果你需要 push 代码无论公开还是私有仓库repo这个 scope 都要勾上。如果你用 GitHub Actions 且 workflow 里需要向仓库写入文件还需要额外勾选workflow。一个必须强调的细节Token 只会完整显示一次。生成之后页面会显示一段字符串关闭页面或刷新之后就再也看不到了。所以生成后要立刻复制保存到密码管理器或本地安全的位置不要提交进代码仓库。4.2 三种使用 Token 的方式与安全对比Token 拿到之后使用方式有三种安全程度不一样。第一种把 Token 直接拼在 remote URL 里git remote add origin https://用户名:TOKENgithub.com/用户名/仓库名.git这种方式最直接但也是最不推荐的——Token 会出现在git remote -v的输出里也会出现在 shell 历史记录中如果直接粘贴执行的话。一旦这个项目被分享截图、上传日志Token 就等于泄露了。第二种使用普通 HTTPS 地址push 时按提示输入git remote add origin https://github.com/用户名/仓库名.git git push -u origin main执行 push 后 Git 会提示输入用户名和密码用户名填 GitHub 用户名密码字段粘贴 Token不是你的登录密码。输入成功后Git 会把凭据保存到系统凭据管理器里Windows 凭据管理器 / macOS 钥匙串下次 push 不再弹出输入框。第三种手动配置 credential helpergit config --global credential.helper store这个配置会把凭据以明文形式保存到~/.git-credentials文件里。Windows 上更推荐用manager作为 helper默认配置它把凭据保存在 Windows 凭据管理器中安全性更好。对比来看我个人的建议是日常个人开发用第三种方式中的managerWindows 默认就是配合短有效期的 Token既能自动记住凭据又能在 Token 泄露时将损失控制在一定范围内。4.3 高频 Token 报错与处置方案Token 方式最常见的几个报错这里逐个拆解报错一remote: Support for password authentication was removed.这个报错说明你输入的是账号密码而不是 Token。2021 年之后 GitHub 只接受 Token 或 SSH key 作为 Git 操作认证凭据。解决方案在密码框里粘贴 Token或者改用 SSH 方式。报错二remote: Permission to user/repo.git denied to xxx大概率是 Token 的权限范围不够。检查一下生成 Token 时是否勾选了repo这个 scope以及 Token 是否已经过期。如果 Token 是在另一个账号下生成的也会出现类似提示。报错三Your access token could not be refreshed. Please log out and sign in again.这个报错主要出现在 VSCode 或 GitHub Desktop 这类工具里。意思是缓存在本地的认证信息已经失效Token 无法自动刷新了。解决办法在 VSCode 里按CtrlShiftP输入GitHub: Sign out退出登录然后再GitHub: Sign in重新走一遍浏览器授权流程。报错四sign-in could not be completed token exchange failed: token endpoint returned status 403 forbidden: country这类报错通常和当前网络环境有关——GitHub 的 Token endpoint 做了区域风控当出口 IP 所在地属于被限制区域时会返回 403。遇到这个问题先确认浏览器能否正常打开 GitHub 并登录如果浏览器可以但工具不行尝试清掉 VSCode 的缓存登录态后重新走浏览器认证。5. push 失败排障实录一条完整排查链路的复盘5.1 从输入密码失败到改用 Token的完整经过这一节用一条真实的场景线索把上面提到的坑串起来走一遍让你了解出问题时应该怎么思考。假设你今天刚在新电脑上配置好 Git项目写完了执行git pushGit 弹窗要求输入用户名和密码。你输入了 GitHub 的登录密码结果报错remote: Support for password authentication was removed. Please use a personal access token instead.这时你的第一反应不应该是换个密码再试而是应该意识到GitHub 不再支持密码认证了。正确路径是二选一要么走 SSH 方式要么用 Token。如果你现在时间紧想快点把代码推上去最快的办法是去后台生成一个 Token用上文的第二种方式输入进去。这一步能立刻解决问题适合临时应急。但要记住Token 方式推上去之后你不应该就此打住。因为 Token 有有效期假设你生成了 90 天有效的 Token三个月之后你再次 push 时Git 会提示认证失败你可能会陷入为什么昨天还好好的今天不行了的困惑。5.2 第二天 push 又失败从 Token 过渡到 SSH接上面的场景。假如你当时为了方便把 Token 粘贴进 remote URL那么下一次 push 可能也会出问题——不是 Token 过期了而是你的 remote URL 里带着一个已经失效的 Token。每次 push 都尝试用这个死掉的 Token 去认证自然一直失败。这时候正确操作是先把 remote 重置为干净的 HTTPS 地址然后重新触发认证流程git remote set-url origin https://github.com/用户名/仓库名.git git push随后按提示输入新的用户名和 TokenGit 会重新把凭据保存到本机。如果你发现每次 push 都弹框、且输入正确 Token 仍然失败可以去 Windows 凭据管理器里找到git:https://github.com相关的记录手动删掉旧的凭据再重新 push 输入一次。在这个反复和 Token 搏斗的过程中很多人会意识到SSH 方式一旦配置好就没有这些续期、失效、刷新的问题。于是你决定切换到 SSH。5.3 SSH 权限报错的根因定位路径切换到 SSH 方式你按部就班地生成密钥、注册公钥然后执行ssh -T gitgithub.com测试结果报错Permission denied (publickey).这时候不要慌按下面的顺序排查第一步确认 ssh-agent 里有没有加载私钥eval $(ssh-agent -s) ssh-add -l如果输出是The agent has no identities.说明私钥没有加载执行ssh-add ~/.ssh/id_ed25519加载。第二步用调试模式看看具体卡在哪一步ssh -vT gitgithub.com输出里会显示它尝试读取了哪些 key 文件、服务器返回了什么信息。如果看到load pubkey /c/Users/xxx/.ssh/id_ed25519: invalid format说明密钥格式有问题重新生成一对密钥即可。第三步如果报错是前面提过的Bad owner or permissions on C:\Users\xxx/.ssh/config先按 3.3 节的权限修复方式处理再测试。把这条路径走通之后SSH 的git push才能像无感一样顺畅。整个过程本质上是先确认认证链路的每一环都通畅再去执行业务操作。很多新手之所以被这类问题折磨是因为跳过了中间验证步骤直接在git push失败后开始乱改配置。5.4 高频 git push 报错速查表报错信息常见原因解决方向Permission denied (publickey)SSH 私钥未加载或公钥未注册用ssh-add -l和ssh -T gitgithub.com逐段排查Repository not found仓库名写错 / 没有该仓库权限 / 账号不对检查 remote URL 拼写、账号身份Updates were rejected远端有本地没有的提交先git pull --rebase origin main再 pushSupport for password authentication was removed输入了密码而不是 Token改用 Token 或 SSH 认证token expiredToken 超期去 GitHub 后台重新生成 Token 并更新凭据fatal: The current branch master has no upstream branch没建立本地分支和远端分支的关联用git push -u origin master或git push -u origin main这张表建议收藏。每一个报错背后都有明确的触发条件对照排查比凭空猜测高效得多。6. SSH 还是 Token我的选型方法和长期习惯6.1 两种方式的核心对比两种方式没有绝对的优劣关键是匹配使用场景。一句话总结SSH 适合长期、高频、个人电脑Token 适合临时、多变、共享环境。维度SSH 密钥Token配置复杂度首次配置稍复杂生成密钥、注册公钥、测试连接创建简单但每隔一段时间要更换使用体验配置好后长期无感push 无需任何输入过期后需重新生成和更新凭据安全模型私钥文件保护可以设 passphraseToken 可设权限范围和有效期可即时作废泄露风险私钥泄露影响大需要重新生成一对单点泄露影响范围小删掉该 Token 即可适用场景自己的电脑、长期项目公司机器、公用机器、CI/CD 自动化从 GitHub 官方角度两种方式都完全支持。你完全可以根据自己的情况混用比如个人电脑用 SSH公司电脑用 Token。6.2 按场景选型的四条建议第一个人开发机、主力电脑我建议使用 SSH。配置一次大约 10 分钟之后每天几十次 push 都不用想认证的事。这也是我自己最常用的方式。第二公司分配的电脑我建议使用 Token 短有效期比如 30 天因为公司电脑可能存在安全合规要求不适合把私钥长时间留在机器上而且离职时收回权限也方便。第三CI/CD 自动化部署场景Token 是主流方案但更推荐使用 GitHub 官方的 Deploy Key 或者直接在 Actions 里用内置的 secrets 机制避免把 Token 写死在配置文件里。第四维护多个代码托管平台的开发者可以在~/.ssh/config里为不同平台配置不同的私钥文件用 Host 别名做区分。比如 GitHub 用默认密钥Gitee 用另一把密钥。这也是 SSH 方式的一个隐藏优势——一个机器管理多个平台账号非常清晰。6.3 一些日常使用的小习惯最后分享几个我在实际使用中养成的小习惯每一个都有过教训Token 一定要进密码管理器。我有个朋友把 Token 直接写在项目根目录的 README 里用的时候图方便结果仓库公开后 Token 被爬虫抓走GitHub 直接发了安全告警邮件。Token 泄露之后唯一补救措施就是立刻吊销并重新生成整个流程非常麻烦。别图省事密码管理器不贵也不难用。不定期检查 remote URL。执行git remote -v确认 remote 地址里没有拼接 Token。如果发现以前手误把 Token 加进去了用git remote set-url origin立刻改回干净地址然后再吊销那个 Token 重新生成。push 之前想清楚再 commit。热搜词里经常会有人搜git commit --amend确实也是一项实用操作——当你发现上一次 commit 的 message 写错了或者漏掉了某个文件可以在 push 之前用git commit --amend -m 新的提交信息来修改最近一次提交。但要注意这条命令只能改还没有 push 出去的提交一旦已经推送到远端amend会导致本地历史与远端不一致再 push 就需要强制推送会带来不少麻烦。我现在所有个人项目的远程仓库统一走 SSH公司的机器上则配了有效期很短的 Token每次换新环境都从头走一遍完整链路。坦白说第一次配 SSH 花了一个下午第二次在新电脑上配只花了十分钟再后来已经完全变成了肌肉记忆。这也是我为什么花这么多篇幅把原理讲清楚的原因——你真正理解了 SSH 和 Token 各自的运作方式、适用边界和常见坑以后遇到任何认证相关的问题都能快速定位到对应的环节而不是在报错信息面前干瞪眼。
返回列表