You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firestore规则问题:已共享用户无法访问照片文档排查

问题原因及解决方案

1. Firestore规则逻辑完全颠倒

你写的规则是在判断「文档所有者的邮箱是否在该文档的shared数组里」,这逻辑完全反了——正常应该是「当前登录用户的邮箱是否在shared数组里,或者用户本身就是文档所有者」。原规则只会在owner的邮箱被自己加入shared列表时才允许访问,这显然不符合需求。

修正后的规则:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /photos/{photo} {
      allow read if: 
        // 用户是文档所有者,或者邮箱在shared数组中
        request.auth.token.email == resource.data.emailOwner ||
        request.auth.token.email in resource.data.shared;
    }
  }
}

2. 查询代码的条件错误

你的查询用了whereField("emailOwner", arrayContains: user.email),但emailOwner是单个字符串类型的字段,arrayContains是专门用来查询数组类型字段是否包含指定元素的方法,这里完全用错了字段。

你需要查询的是两类文档:

  • 自己作为所有者的文档(emailOwner等于当前用户邮箱)
  • 被共享给自己的文档(shared数组包含当前用户邮箱)

修正后的Swift查询代码(并行查询后合并去重):

func getItems() async throws -> [Item] {
    guard let userEmail = user.email else {
        throw NSError(domain: "AuthError", code: 0, userInfo: [NSLocalizedDescriptionKey: "用户未登录"])
    }
    
    // 查询自己所有的照片
    let ownerQuery = photoCollection.whereField("emailOwner", isEqualTo: userEmail)
    // 查询共享给自己的照片
    let sharedQuery = photoCollection.whereField("shared", arrayContains: userEmail)
    
    // 并行执行两个查询
    let (ownerSnapshot, sharedSnapshot) = try await (ownerQuery.getDocuments(), sharedQuery.getDocuments())
    
    // 转换并合并结果
    var items: [Item] = []
    items += try ownerSnapshot.documents.compactMap { try $0.data(as: Item.self) }
    items += try sharedSnapshot.documents.compactMap { try $0.data(as: Item.self) }
    
    // 按ID去重,避免自己的照片同时在shared列表里重复出现
    let uniqueItems = Array(Set(items))
    return uniqueItems
}

额外注意点

  • 确保Firestore规则中启用了身份验证,可在规则顶部添加基础校验:allow read, write: if request.auth != null;
  • 检查shared数组中存储的邮箱格式是否和用户登录的邮箱完全一致(大小写、拼写错误都会导致匹配失败)

内容的提问来源于stack exchange,提问作者matteog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 14:13:22