Firebase安全规则需匹配查询吗?Firestore帖子查询权限被拒
Firestore查询用户交互帖子权限被拒问题解决
我尝试通过Firestore查询获取两个用户之间的所有交互帖子,但遭遇权限被拒。以下是相关信息及解决办法:
帖子文档结构
posts集合中的文档包含以下核心字段:
{ "to": "接收帖子的用户UID", "from": "发送帖子的用户UID", "queryIdentifier": "uidsToQueryIdentifier(接收方UID, 发送方UID)", // 其他字段... }
queryIdentifier生成逻辑
创建帖子时,通过以下函数生成queryIdentifier,确保两个用户的UID组合顺序一致:
const uidsToQueryIdentifier = (uid1, uid2) => { if (uid1 < uid2) { return uid1 + "_" + uid2; } return uid2 + "_" + uid1; }
当前配置
安全规则
match /posts/{postId} { allow read: if request.auth.uid == resource.data.to || request.auth.uid == resource.data.from; allow write: if true; }
客户端查询代码
用户已完成认证并持有UID,但执行以下查询时仍被拒:
const queryIdentifier = uidsToQueryIdentifier(user.uid, friend.uid); let query = firestore().collection("posts") .where("queryIdentifier", "==", queryIdentifier) .orderBy("createdAt")
问题原因
Firestore的安全规则是逐文档校验,但原查询仅过滤了queryIdentifier,规则无法提前确认返回的所有文档都满足request.auth.uid是to或from的条件——因为规则无法直接将queryIdentifier和to/from字段关联起来,导致查询被拦截。
解决办法
有两种可行的优化方向:
方向1:修改客户端查询,补充用户身份过滤
在查询中添加当前用户是发送方或接收方的条件,让规则能确认返回的文档都符合权限要求:
const queryIdentifier = uidsToQueryIdentifier(user.uid, friend.uid); // 方式1:用in操作符过滤to字段 let query = firestore().collection("posts") .where("queryIdentifier", "==", queryIdentifier) .where("to", "in", [user.uid, friend.uid]) .orderBy("createdAt") // 方式2:用OR组合from/to的条件(需Firestore支持OR查询) query = firestore().collection("posts") .where("queryIdentifier", "==", queryIdentifier) .where(firestore.or( firestore.where("from", "==", user.uid), firestore.where("to", "==", user.uid) )) .orderBy("createdAt")
方向2:优化安全规则,直接校验queryIdentifier
修改规则,通过拆分queryIdentifier来验证当前用户是否属于交互双方,这样原查询无需修改即可通过:
match /posts/{postId} { allow read: request.auth.uid in resource.data.queryIdentifier.split("_"); allow write: if true; }
这种方式利用queryIdentifier的组合特性,直接判断当前用户UID是否在组合字符串中,规则逻辑更简洁,且能和原查询条件匹配。
内容的提问来源于stack exchange,提问作者Minh Luong
相关产品推荐
相关产品推荐

