十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Gitee SSH公钥配置与Permission denied报错排查

Gitee SSH公钥配置与Permission denied报错排查 1. 这个报错到底在说什么gitgitee.com: Permission denied (publickey). Could not read from remote repository.这行红字几乎每个用 Git 推过代码的人都撞见过。它的字面意思是你以 SSH 协议去连 gitee.com服务器端拒绝了你的身份证明原因是它没认出来你是谁。后面那句Could not read from remote repository是连带结果——身份都没通过自然读不到远端仓库。我先说清楚这个报错的适用人群只要你是通过gitgitee.com:用户名/仓库名.git这种 SSH 地址做 clone、pull、push 的就属于这个报错的高发群体。反过来如果你用的是https://gitee.com/...开头的地址出现的是要你输账号密码那一套跟本文完全是两条线别混着排查。这个区分很关键我见过太多人拿着 HTTPS 的仓库在那边反复配 SSH 密钥方向从一开始就错了。为什么值得单独写一篇因为这个报错的信息量其实很少它只说“公钥认证失败”但导致失败的可能有五六个完全不同的原因密钥压根没生成、生成了但没加到 Gitee、加错了账号、本地 SSH 代理没起来、连到了错误的 host、文件权限过宽导致 SSH 主动拒用私钥、甚至是你机器上装了多个 SSH 客户端互相打架。如果只知道“复制公钥粘贴到设置里”这一个动作遇到剩下的情况就只能干瞪眼。这篇文章我打算按真实排查顺序来写先把这个认证链路讲明白让你知道 SSH 登录时到底发生了什么再讲清 Gitee 上该配什么、本机该生成什么然后给出手把手的完整实操包括验证方式和每一步的验证预期最后把常见坑整理成速查表。全程基于通用 Git 与 SSH 的标准行为来讲你照着做能直接复现不需要任何额外环境。1.1 为什么 SSH 会被拒绝而密码能过很多人第一次配密钥时都会有这个疑问我明明能用网页登录 Gitee也能用账号密码 clone凭什么 SSH 就说我没权限这里得先理解公钥认证这套机制的设计初衷。SSH 的认证走的是非对称加密那套思路。你在本地生成一对密钥一个叫私钥一个叫公钥。私钥永远留在你机器上绝不外传公钥可以随便给它的作用就是“锁”。你把公钥交给 Gitee等于告诉它以后凡是能用这把锁对应的钥匙私钥解开挑战的人就是我。登录时 Gitee 拿你上传的公钥发一道加密题只有持有对应私钥的客户端能解出来并发回正确答案服务器验证通过就放行。所以Permission denied (publickey)的本质只有一句话服务器手里那把“锁”和你本机这把“钥匙”对不上。可能是服务器根本没拿到锁公钥没上传可能拿的是别的锁上传到了另一个账号或另一个 Key 条目也可能你手里拿的不是钥匙而是一把断了的私钥路径写错、文件权限不对、SSH 代理里没加载。密码认证和公钥认证是两条平行的验证通道。Gitee 为了账号安全对 SSH 方式默认只认公钥不接受密码。所以你用 HTTPS 那套账号密码的经验套到 SSH 上一定会碰壁。理解了这一点排查时就知道该查什么了要么查服务器端的锁列表要么查本机的钥匙位置和状态二者必居其一。1.2 一条命令先把问题范围缩到最小别急着改配置先用一条命令确认报错是否真实存在、以及发生在哪一层ssh -T gitgitee.com-T的意思是禁止分配终端只做认证测试。这条命令的结果是整个排查的分水岭只有两种第一种输出类似Hi 你的用户名! Youve successfully authenticated, but GITEE.COM does not provide shell access.这说明认证已经过了SSH 通道完全正常。那你的Permission denied大概率是仓库地址写错了、或者仓库本身不存在、或者你对该仓库没有权限而不是密钥问题。这种情况下去检查git remote -v的输出把地址修正即可。第二种仍然输出Permission denied (publickey)。这就坐实了是密钥层面的问题继续往下走。我强烈建议把这条命令养成习惯。它能省掉大量无效排查。很多人一看到报错就去重新生成密钥而实际上他可能只是 remote 地址拼错了仓库名。注意ssh -T第一次连接会问你要不要信任这个主机指纹输入 yes 回车即可。这一步是正常的不是报错。如果你看到的提示是主机指纹变了之类的警告先别急着 yes确认是不是网络环境或中间设备导致的避免误信。2. 动手之前把这几个概念分清楚这一节我想把几个新手最容易搅在一起的概念掰开。它们的混淆是绝大多数“配了半天还是失败”的根源。2.1 本地公钥、Gitee 公钥、账号三者的绑定关系你要建立的心智模型是这样的一个链条本地私钥留在电脑绝不外传→ 对应本地公钥一串以ssh-rsa或ssh-ed25519开头的文本→ 粘贴到 Gitee 的 SSH 公钥设置里 → 归属到某个 Gitee 账号。这个链条里有三个独立的“对不上”的点每个都会导致本文的报错一是本地公钥和 Gitee 上存的那条文本不一致比如你重新生成了密钥但 Gitee 上还是旧的。二是公钥飘到了另一个账号下面比如你有两个 Gitee 账号或者把公钥加到了同事的账号上。三是本地有多个密钥文件SSH 默认只加载其中某一个而你上传的是另一个。所以配密钥这件事正确的顺序是先确定本机现在正在用哪把钥匙再去 Gitee 确认这把钥匙的公钥是不是已经存在。顺着链条走奇奇怪怪的问题都会现形。2.2 加密算法选哪个RSA 还是 Ed25519生成密钥时要选算法和位数这一步很多人是照着某篇老教程抄的抄完能用就不管了。但我建议你用 Ed25519理由有这么几条。RSA 是经典算法兼容性最好位数一般选 4096。它的固定文本串很长某些界面粘贴或换行处理不当时容易出问题。Ed25519 是现代椭圆曲线算法密钥短、生成快、安全性在相同强度下更优Gitee 支持良好。还有一个实际好处Ed25519 的固定前缀短不容易在复制粘贴环节被截断或者在网页端被错误换行。那什么情况下还用 RSA如果你的环境非常老或者某些集成工具依赖老的加密库那就退回 RSA 4096。否则我默认推荐 Ed25519。下面实操里我会给你两个版本。2.3 Gitee 上到底要填什么别填反了这是新手最高频的翻车点把私钥粘到 Gitee 上去了。私钥文件没有.pub后缀比如id_ed25519公钥有.pub后缀比如id_ed25519.pub。你要交给 Gitee 的永远是那个.pub里的全部内容起止完整一行不落不要自己加换行不要删首尾字符。私钥泄露是什么后果就不用我多说了等于把钥匙复制了一份给全世界。所以养成习惯操作时只看.pub文件另一个文件连打开都别打开。3. 完整实操从零把这把钥匙配好下面这套流程我从头到尾走一遍你按步骤来。3.1 第一步先看看本机是不是已经有密钥了很多人电脑里其实早就有密钥只是自己忘了。先查一下ls -al ~/.sshWindows 上如果你用 Git Bash~就是你的用户目录命令一样有效。看输出里有没有id_ed25519/id_ed25519.pub或者id_rsa/id_rsa.pub这样的配对。有的话直接跳到第 3.3 节去读公钥别重复生成。如果目录根本不存在或者里面空空如也就进入下一步生成。还有一种情况是目录存在但里面有个known_hosts文件这个是记录你连过哪些服务器的指纹跟密钥无关不用管它。3.2 第二步生成一对新密钥Ed25519 版本ssh-keygen -t ed25519 -C 你的邮箱或备注RSA 版本给老环境兜底ssh-keygen -t rsa -b 4096 -C 你的邮箱或备注解释一下这几个参数。-t指定算法类型-b只在 RSA 下指定位数-C是注释会附在公钥末尾纯粹给你自己看的备注填邮箱或者“我的主力机”都行不影响认证。执行后它连问你三件事。第一问文件保存路径默认回车就是~/.ssh/id_ed25519。第二问和第三问是同一件事的两次输入——设置一个 passphrase口令。这里我要多说一句因为这是很多人纠结的点。口令不是必填的直接两次回车留空生成的就是无口令密钥用起来最省事适合个人开发机。如果你设置了口令每次用它认证都要输一遍虽然可以用ssh-agent缓存但配置就多一层。我的常规做法是个人机器留空共享机器或公司电脑设置口令并配合 ssh-agent。安全性上有口令的密钥即使文件被拷走也不能直接用价值很高。生成成功后会打印一个随机的图案和指纹最后告诉你公钥已保存在哪个路径。3.3 第三步取出公钥内容cat ~/.ssh/id_ed25519.pub输出的就是那一整行文本形如ssh-ed25519 AAAA...(一长串)... 你的备注。全选复制注意从头复制到尾不要漏掉开头的算法前缀也不要漏掉末尾的备注。如果你的编辑器或终端有自动换行显示看着像两三行实际复制出来是连续的一行这没关系正常。但如果你手动敲进 Gitee 时换行了那就是错的。永远用复制粘贴别手打。提示复制后建议先在本地文本编辑器里粘一下肉眼确认它是完整的一行。这一步花五秒能省掉后面半小时的困惑。3.4 第四步粘贴到 Gitee 的公钥设置里登录 Gitee进个人设置找到「安全设置」里的「SSH 公钥」页面点「添加公钥」。这里通常要填三样标题、公钥内容有的版本还会让你确认有效期。标题随便写方便你以后识别就行比如“公司台式机”。把刚才复制的完整公钥内容粘进公钥框不要改动任何字符不要删首尾空格。有的浏览器会好心给你做格式化粘完后可以再看一眼首尾是否完整。保存时会让你做一次账号身份验证输密码或扫码即可。保存成功后列表里会出现这条公钥的指纹和标题。3.5 第五步验证是否打通回到终端再跑一次ssh -T gitgitee.com预期输出是Hi 你的用户名! Youve successfully authenticated...。看到这句说明整条链路已经通了。这时候再回到你的项目目录执行git pull或者git push刚才的报错应该消失。如果还是Permission denied别慌继续看第 4 节的排查方法。99% 的情况是公钥没粘全、或者本机用的不是这把钥匙。3.6 第六步如果之前 remote 用的是 HTTPS换成 SSH有些人的仓库地址本来就是 HTTPS 的密钥配好了照样连不上因为走的是另一条通道。先看清楚git remote -v如果输出里是https://gitee.com/...说明你该换地址了。改成 SSHgit remote set-url origin gitgitee.com:用户名/仓库名.git改完再git remote -v确认一次然后重新 pull/push。这个改动只影响这个仓库的远端地址不影响你其它配置。仓库地址可以在 Gitee 仓库页面点「克隆/下载」按钮拿到选 SSH 那一栏直接复制。4. 排查表还是失败逐个对照配完了还不行那就得系统排查。下面这张表是我这些年攒下来的按“最容易踩”的排前面。现象 / 检查点可能原因处理方式ls ~/.ssh里有多个 id 文件存在多把钥匙SSH 用了非预期的那个用ssh -vT gitgitee.com看实际加载了哪个文件公钥末尾有空格或换行复制粘贴时带上了多余空白重新从.pub完整复制确认首尾无空白公钥粘的是私钥内容把没有.pub后缀的文件内容填了上去换成.pub文件的内容公钥加在了另一个账号下多账号混淆登录对应账号删掉后加到正确的账号ssh -vT显示 private key 被忽略私钥文件权限过宽chmod 600 ~/.ssh/id_ed25519ssh -vT显示根本没加载 key文件不在默认路径或名字不对用-i指定路径或改名为默认名报错里出现别的 IP 或陌生 host连到了并非预期的服务器检查网络代理与 DNS 解析确认gitgitee.com地址本身正确之前能连突然报错主机指纹或本地 key 变了核对known_hosts确认是预期内的变更后再处理4.1 用 verbose 模式看清真实过程普通的报错信息量太少排查时请加-vssh -vT gitgitee.com-v会打印详细握手过程。你重点找这几类行一是debug1: identity file ...它会列出 SSH 尝试加载了哪些私钥文件。看看里面有没有你刚生成的那个或者有没有加载失败的提示。二是debug1: Offering public key: ...这是它实际向服务器提交的公钥。对比一下这行里的公钥指纹和你上传到 Gitee 的是不是同一个。三是最后的Authentications that can continue: publickey说明服务器只接受公钥方式。实际排查中绝大部分问题在identity file这几行就能看出来。如果加载的路径和你生成的对不上就是路径或命名问题如果它根本没列出任何 key就是文件不存在或权限被拒。verbose 输出很长不用全看盯住上面三类就够了。4.2 是不是机器上装了多个 SSH 客户端Windows 用户尤其容易遇到这个。你可能装了 Git for Windows 自带的 SSH又装了系统自带的 OpenSSH还可能有些工具带了自己的 SSH 实现。这几个客户端的密钥目录、配置文件可能都不一样结果就是你在 A 里生成并配好的密钥实际操作时调用的是 BB 里什么都没有。判断方法在报错的那个终端环境下执行where sshWindows或which sshLinux/macOS看看调用的是哪一个。再看它的密钥目录在哪。统一到同一个客户端问题基本就解决了。我的建议是如果你用 Git Bash就尽量在这个终端里做密钥生成和测试保持一整套环境一致。4.3 配置文件帮你管好多钥匙如果你本机有多个代码平台账号靠默认加载很容易乱。这时候.ssh/config能帮大忙。在~/.ssh/config里加一段Host gitee.com HostName gitee.com User git IdentityFile ~/.ssh/id_ed25519 IdentitiesOnly yes这段配置的意思是凡是连接 gitee.com就固定使用id_ed25519这把私钥IdentitiesOnly yes强制只用指定的这一把不再瞎试其它 key。这一招能解决很大一类“明明配了却用错 key”的问题。注意HostName和User的写法要和 SSH 地址对应SSH 地址gitgitee.com里git是用户名gitee.com是主机名别搞反。5. 我踩过的坑和实操心得下面这几条是文档里通常不会写、但实际很坑的经验。第一个坑密钥有有效期这种概念。有的平台允许给公钥设置有效期过期后认证自然失败而报错信息跟本文一模一样不会告诉你是过期了。如果你之前好好的突然不行先去公钥列表看看是不是那条公钥已经过期或者被删了。第二个坑共享或克隆环境里~指向不对。有些工具或脚本运行时的用户目录不是你以为的那个于是密钥在 A 目录生成程序却在 B 目录找自然找不到。排查时可以把~/.ssh展开成绝对路径打印出来确认。第三个坑复制公钥时被编辑器吞掉换行。有些编辑器对超长单行做软换行显示你全选复制看似完整其实可能带了不可见字符。稳妥办法是复制后用一个纯文本编辑器如记事本、nano粘一下确认是一行。第四个心得改完配置后别急着重开先跑ssh -T gitgitee.com验证。养成“改一步验一步”的节奏比一口气改一堆再排查要高效得多。我见过有人同时改了密钥、改了 config、换了 remote出问题时根本不知道是哪一步引入的。第五个心得.ssh目录的权限别乱动。Linux 和 macOS 上如果这个目录或私钥文件权限过于开放比如其他用户可读SSH 会拒绝使用它而且报错不一定直白。稳妥的权限是目录 700私钥 600公钥 644。Windows 上通常不用操心这些但 Git Bash 下如果是从 WSL 交叉访问可能会出现类似的权限提示。第六个坑网络中间设备或公司网络可能拦截或改写 SSH 流量表现为连接被重置或指纹不一致。如果你的环境比较特殊先尝试换一个网络环境确认是否与本地配置有关再决定后续动作。6. 一劳永逸把免密和自动化一起搞定密钥配好之后还有不少人会问为什么我每次 push 还要输口令那是因为你给密钥设了 passphrase或者根本还在用 HTTPS。如果你设了口令用ssh-agent缓存起来即可。启动 agent 并把私钥加进去eval $(ssh-agent -s) ssh-add ~/.ssh/id_ed25519这样在当前会话里认证一次后面就不用反复输了。想开机自动加载可以把这个写进 shell 的启动配置里注意不同 shell 的配置文件不一样bash 是.bashrczsh 是.zshrc。如果你用的是 WindowsGit for Windows 自带的凭据管理器和 ssh-agent 都能帮你缓存。开启后第一次输完后续就自动带了。还有一个思路值得提就是给不同用途配不同的 key。比如个人项目一把、工作项目一把对应到.ssh/config里不同的 Host 别名。这样做的好处是一把泄露不牵连全部而且排查时指向明确。代价就是管理成本高一点对大多数人来说一把主力 key 加 config 绑定已经足够。把密钥、config、代理这三件事配顺之后日常的 clone、pull、push 基本就再也见不到那行红字了。真正会让它重新出现的通常是换电脑、重装系统、更换账号、或者太久没动过忘了当初怎么配的——这时候回到第 1.2 节那条ssh -T命令重新走一遍本文的排查顺序就好。
返回列表