4.1 安全避坑:密钥泄露、规则裸奔与数据导出风险
安全这一节,我不打算讲理论,只讲三个真实发生过、且至今仍在反复发生的事故。它们的共同点是:出事之前,当事人都不觉得自己做错了什么。
事故一:把配置当成了私密信息
新项目接入 Firebase,控制台会给一段前端配置对象,里面有 apiKey、projectId 这些字段。很多人的第一反应是:这是钥匙,必须藏好。于是想方设法把它塞进环境变量、混淆进构建产物,甚至为此搭出一套复杂的注入机制。
真实情况是:这段配置本来就会跟着前端代码到达每一个用户的浏览器,打开开发者工具就能看全。它不是私密信息,公开是设计使然。
那真正的防线在哪?两处。第一处是安全规则:Firestore 和 Cloud Storage 的每一次读写都要过规则这一关,配置只负责告诉客户端数据库在哪,能不能进由规则说了算。第二处是身份认证侧的配置,比如登录方式的授权域名、验证码类能力的滥用防护,这些才需要认真管。
理解了配置可见不等于不安全,你会砍掉大量无用的藏钥匙代码,把精力放回真正该花的地方——规则设计。
事故二:规则裸奔
最经典的一幕:开发期间为了图省事,规则写成全放开模式,读写一概放行。项目顺利上线,规则忘了收。数据库就这样裸奔在公网上,直到某天被扫到。
后果通常按顺序发生:先是数据被整库爬走,接着要么被要挟,要么被灌进一堆垃圾数据,最后账单和口碑一起崩。别以为测试库就安全——爬虫不在乎库里是不是假数据,垃圾写入和产生的费用在乎。
正确姿势其实就三句话:
- 默认拒绝:规则的底座永远是全拒绝,每个集合只在确有需要时按条件放开。
- 按需放开:给规则做加法之前先问一句,这个开放的最小边界是什么,还能不能再收一收。
- 上线前评审:把规则检查当成发版动作的一部分,像看代码 diff 一样看规则 diff。
一份可以直接抄进流程的上线前清单:
- [ ] 没有任何一条规则包含无条件放行
- [ ] 涉及用户数据的读写都校验了登录态与归属
- [ ] 写操作校验了字段类型、大小和取值范围
- [ ] 规则文件已提交版本控制,本次变更有 diff 可查
- [ ] 规则单测在模拟器中全部通过
事故三:私钥进了前端或公开仓库
和配置对象不同,Admin SDK 的服务账号私钥是真正的钥匙:拿到它就等于拿到绕过全部安全规则、直接读写整个数据库的管理员权限。它只应该出现在服务端。
但事故总在发生。有人图省事,把服务端初始化代码直接搬进前端,把管理端 SDK 打包给了浏览器;有人把含私钥的密钥文件提交进了公开仓库。后者尤其危险——有机器人专门盯着新提交做扫描,从私钥上线到被利用,时间以分钟计。
正确的做法并不复杂:
- 私钥只放环境变量或密钥管理服务,永不进代码仓库
- 仓库配置忽略规则,把密钥文件挡在提交之外
- 给服务账号分配最小权限,只授予业务真正需要的角色
- 一旦怀疑泄露,立即在控制台撤销并轮换密钥,不要心存侥幸
数据导出风险与定期审计
还有一类风险没有具体的钥匙,却同样致命:只要某条读规则开得太宽,任何人都能分页遍历整个集合,把数据一点点导干净。规则评审时不要只盯着写操作,读的边界同样要一条条过。
规则也不是写完就完的东西。我的习惯是把规则审计做成周期性动作:每月看一次规则 diff 和各集合的引用关系;每季度在模拟器里跑一遍规则单测;有条件的话,把规则评审纳入新人上手的必读流程。规则变更是 diff 最小、后果最大的变更,值得多看一眼。
收尾一张表:
| 事故 | 后果 | 预防 |
|---|---|---|
| 把配置当私密信息 | 精力浪费在藏不该藏的东西上,真正的防线反而没人管 | 理解公开是设计使然,安全预算投给规则与认证配置 |
| 规则裸奔 | 数据被爬、被灌垃圾数据,费用与口碑双输 | 默认拒绝、按需放开、上线前规则评审 |
| 私钥进前端或公开仓库 | 绕过全部规则的管理员权限落入他人之手 | 私钥只进环境变量、最小权限、泄露立即轮换 |
| 读规则过宽被导库 | 数据被分页爬走 | 读边界逐条评审,定期规则审计 |
安全规则的门道远不止这些,但这四类事故覆盖了我见过的绝大多数翻车现场。把它们变成团队的肌肉记忆,你在 Firebase 上就已经比大多数人安全了。
