核验清单

  • 代码仓库里是否曾经把API Key硬编码提交过,哪怕后来在最新提交里删掉了,git历史记录里很可能仍然留着,需要用工具专门排查历史提交而不是只看当前文件
  • 发现调用量或账单异常飙升后,是否第一时间去控制台吊销了那个具体的旧Key并生成了新Key,而不是只去改了登录密码就以为解决了问题
  • 吊销旧Key之后,是否核对过异常时间段内的完整调用日志和账单明细,确认损失金额和调用来源,作为是否需要联系客服申诉的依据
  • 项目里所有用到这个Key的地方(本地环境变量、CI/CD流水线、服务器部署配置)是否都已经同步替换成了新Key,避免某个遗漏的旧引用继续报错或留下安全隐患
  • 代码仓库的公开/私有状态是否设置正确,尤其是把个人项目从私有仓库改成公开仓库之前,有没有重新检查过历史提交里是否残留任何密钥字符串

1. 一个常见场景:Key跟着代码一起进了公开仓库

这类问题最常见的触发方式是:开发者在本地写完一个调用DeepSeek或通义千问API的脚本,图省事直接把API Key以字符串形式写在代码里,测试跑通之后把整个项目推送到GitHub,可能是为了备份,也可能是为了开源分享,却忘了这个仓库是公开的,或者根本没意识到公开仓库里的内容会被自动化扫描工具持续监控。类似GitHub这样的平台上,确实存在专门扫描公开提交历史、抓取符合特定格式的密钥字符串的自动化脚本,一旦抓到形似有效API Key的字符串,很快就会被拿去测试是否可用,可用的话就会被用来发起大量调用请求,直到账户余额耗尽或被平台风控拦截为止。

2. 两套凭证体系:登录密码管什么,API Key管什么

要理解为什么账号密码没事但账单被刷爆,得先弄清楚开发者账号体系里其实并存着两套完全独立的凭证。第一套是"登录账号密码",这是用来登录厂商官网控制台(比如DeepSeek开放平台或阿里云百炼控制台)的凭证,登录之后能看到账单详情、修改账户设置、管理团队成员、查看用量报表等,这一套凭证保护的是"谁能进入管理后台"。第二套是"API Key",这是一串由平台生成的加密字符串,专门用来在代码里调用付费的模型接口,请求时把它放进HTTP请求头的Authorization字段(形如`Bearer sk-xxxx`),服务器验证这串字符串有效就直接处理这次调用请求,全程不需要,也不会去校验发起请求的这一方到底知不知道账号的登录密码。这两套凭证从设计目的上就是分开的:一套面向"人"用浏览器登录管理,一套面向"程序"在代码里高频调用,混在一起管理反而不利于精细化的权限控制。

3. 为什么攻击者能疯狂调用,账号登录记录却干干净净

正因为API Key的调用路径根本不经过"登录"这个动作,攻击者从公开仓库里拿到一串有效的Key之后,可以直接拿着它向`api.deepseek.com`或百炼的API网关发起请求,这个过程只是一次普通的HTTP接口调用,从平台的角度看和开发者本人用同一个Key正常调用没有任何区别,也就不会在账号的登录活动记录、登录设备列表、登录地理位置这些地方留下任何痕迹——因为攻击者从始至终都没有执行"登录"这个动作,他手里握着的只是一段字符串,不是账号密码,也不需要知道账号密码。这也是为什么很多开发者发现账单异常后第一反应去查登录记录、去改登录密码,却查不出任何异常登录、改完密码调用还在继续发生:登录密码和这次盗刷调用之间,本来就没有关联。

4. 单纯改登录密码为什么解决不了问题,必须去控制台吊销Key

既然攻击者拿走的是Key字符串本身而不是登录凭证,改登录密码只会让"谁能登录控制台"这件事变得更安全,但完全不会影响"谁手里握着那串还没被吊销的有效Key"——泄露出去的Key字符串本身依然是有效的,只要它还没被平台标记失效,任何人拿着它都能继续调用成功,跟账号密码改没改没有任何关系。真正能让这个已泄露的Key失效的唯一方式,是登录控制台,在API Key管理页面找到这个具体的Key,把它删除或吊销(不同平台的具体菜单文字可能不同,比如"删除""禁用""吊销",实际操作路径以官方控制台界面为准,可能随版本调整),之后再创建一个新的Key替换到自己的代码和部署环境里。阿里云百炼官方文档就明确写到,如果API Key泄露了应该立即回到API Key页面删除旧密钥、重新创建,这也印证了"吊销旧Key"才是解决泄露问题的正确路径,而不是"改登录密码"。

5. 发现泄露后的处理步骤:吊销、重建、核查

发现Key疑似泄露或账单出现异常调用之后,比较完整的处理步骤大致是:第一步,第一时间登录控制台,找到那个具体的Key并将其删除或吊销,让泄露出去的这串字符串立即失效,这是最紧急、必须马上做的一步;第二步,生成一个新的Key,替换掉本地开发环境、服务器部署配置、CI/CD流水线里所有还在引用旧Key的地方,确认没有遗漏;第三步,回到控制台的用量记录或账单明细页面,核对异常时间段内具体的调用次数、消耗的额度或费用,作为判断损失规模、以及是否需要联系平台客服说明情况或申请核实的依据;第四步,如果这个Key是通过代码仓库泄露的,还要用工具专门排查该仓库的历史提交记录(不只是当前最新的文件内容),确认历史提交里是否还残留着这个字符串或其他曾经用过的Key,必要时清理仓库历史或干脆废弃旧仓库重新建一个干净的。

6. 日常怎么避免Key被硬编码泄露

与其等泄露之后补救,更值得投入精力的是从日常写代码的习惯上降低泄露概率。具体做法包括:不要把Key以明文字符串的形式直接写进会被提交进版本控制系统的代码文件里,改用环境变量的方式在运行时读取(比如阿里云百炼官方文档给出的做法是设置`DASHSCOPE_API_KEY`环境变量,代码里通过读取环境变量获取Key,而不是写死在源码里);给仓库配置`.gitignore`,把存放密钥的本地配置文件(如`.env`)排除在版本控制之外,避免误提交;有条件的话在控制台给Key配置IP白名单或限定可调用的模型范围,即使Key泄露,攻击者从白名单之外的地址发起调用也会被拦截;面向浏览器、移动端等不可信环境的场景,优先使用官方提供的临时API Key机制(阿里云百炼官方文档提到临时Key有效期最长1800秒),而不是把长期有效的Key直接下发到客户端;此外定期主动轮换Key、把长期未用或已经废弃的旧Key及时删除,也能缩小万一遗漏泄露时的风险窗口。

7. 小结:两套体系分离是设计使然,处理方式也要对应分开

登录账号密码和API Key之所以是两套互相独立的凭证体系,本质上是因为它们保护的对象不同:一个保护"谁能登录管理后台",一个保护"谁能拿着这段字符串调用付费接口",二者从设计上就没有相互验证的关系。这也决定了Key一旦泄露,改登录密码这个动作完全帮不上忙,唯一有效的处置方式是回到控制台把这个具体的Key吊销、重新生成新Key,并核查异常时间段内的调用记录和账单。日常把Key存进环境变量而不是硬编码进代码、配置IP白名单、定期轮换,是能实实在在降低泄露概率的具体做法。