关于Firestore规则严格性及传入数据信任性的技术咨询
Firestore规则严格性与客户端数据信任指南
一、Firestore规则要尽可能严格,遵循「最小权限」原则
Firestore规则是你数据安全的第一道防线,越严格越安全。你应该只给用户完成必要操作的权限,比如:
- 普通用户只能读写自己的用户文档,不能随意访问他人的
- 写入数据时,只能修改预设的字段,且字段值必须符合业务预期
- 针对子集合(比如你的
friendRequests),要单独设置更细粒度的规则,杜绝越权操作可能
二、绝对不能信任客户端传入的任何数据
答案很明确:完全不能信任。客户端代码是完全可篡改的——不管是在浏览器控制台直接修改JS变量、反编译打包后的代码篡改逻辑,还是用工具模拟请求,客户端都能伪造任何传入Firestore的数据,包括你例子里的payload.uid、email、displayName。
举个实际场景:用户打开浏览器控制台,把你的代码里的payload.uid改成任意字符串,Firestore会直接接收这个值,除非你用规则拦截。
不过有个关键例外:Firestore规则中的request.auth对象是绝对可信的。这个对象是从Firebase Auth签发的合法token解析来的,客户端无法伪造request.auth.uid、request.auth.email这些字段,因为token的签名是由Firebase服务器验证过的,规则会自动校验token的合法性。
三、针对你的代码示例,如何设置安全规则
你的代码是向当前用户的friendRequests集合写入一条好友请求,带上了payload里的uid、email和displayName。要防止伪造,规则需要做到以下几点:
service cloud.firestore { match /databases/{database}/documents { // 限制用户只能访问自己的用户文档 match /users/{userId} { allow read, write: if request.auth != null && request.auth.uid == userId; // 对friendRequests子集合的写入规则 match /friendRequests/{requestSenderId} { allow create: if request.auth != null // 确保当前用户是请求接收者(只能修改自己的请求列表) && userId == request.auth.uid // 确保文档ID和写入的uid字段一致,避免内容与ID不匹配 && requestSenderId == request.resource.data.uid // 强制写入的uid必须是发送者的真实认证ID,彻底防止伪造 && request.resource.data.uid == request.auth.uid // 可选:验证写入的邮箱和用户认证的邮箱一致 && request.resource.data.email == request.auth.email; } } } }
规则核心逻辑解释:
request.auth != null:确保只有登录用户才能发起操作userId == request.auth.uid:限制用户只能在自己的friendRequests集合里添加请求(避免用户乱改他人的请求列表)requestSenderId == request.resource.data.uid:保证文档ID和写入的uid字段一致,避免数据混乱request.resource.data.uid == request.auth.uid:强制写入的发送者ID必须是当前登录用户的真实UID,彻底堵死客户端伪造发送者的可能request.resource.data.email == request.auth.email:验证写入的邮箱和用户认证的邮箱一致,防止伪造邮箱信息
如果你的业务是「A用户给B用户发请求」(也就是写入B的friendRequests集合),规则需要调整为:确保写入的文档ID是A的UID,且request.auth.uid等于A的UID,同时可以用exists()方法检查B的用户文档是否存在,避免写入无效数据。
四、额外安全建议
- 如果业务逻辑复杂,建议结合Cloud Functions处理写入:在云函数里再次验证数据合法性,再写入Firestore,形成规则+后端的双重校验
- 定期审计Firestore规则,排查是否存在过度授权的情况
- 对于敏感隐私数据,尽量只在后端处理,不要通过客户端直接写入
内容的提问来源于stack exchange,提问作者Xstyler
相关产品推荐
相关产品推荐

