Firebase Firestore规则配置:仅允许用户访问自身上传的照片
问题:Firestore规则配置实现用户仅访问自己上传的照片
问题背景
我正在开发一款可上传照片的简易APP,使用Firebase Firestore与Storage。每次上传新照片时,会创建如下Item对象:
struct Item: Codable, Identifiable { var id: UUID // photo name var uidOwner: String // uid user owner var emailOwner: String // email user owner var path: String // photo path var shared: [String] = [] }
需要配置Firestore规则,实现仅允许每个用户查看自己上传的照片,当前Firestore数据路径为photos集合下的单文档结构。
当前Firestore规则
当前使用的规则仅针对单文档做权限检查,在Firestore Playground中有效,但在Xcode中执行全集合查询时请求被拒绝(推测是规则无法验证全集合下的文档权限):
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /photos/{photo} { allow read: if resource.data.uidOwner == request.auth.uid; } }
iOS端请求代码(补充编辑)
当前iOS端获取照片列表的代码是直接读取整个photos集合:
func downloadImagesName(){ self.isLoading = true self.itemsPhoto = [] // Reference let imagesCollectionRef = db.collection("photos") imagesCollectionRef.getDocuments(completion: { snapshot, error in if let error = error { print("Errore durante il recupero dei documenti: \(error.localizedDescription)") self.isLoading = false return } snapshot?.documents.forEach { doc in do { let item = try doc.data(as: Item.self) self.itemsPhoto.append(item) if doc == snapshot?.documents.last { self.isLoading = false } } catch { print("Errore durante la conversione dei dati: \(error.localizedDescription)") self.isLoading = false } } self.isLoading = false }) }
解决方案
问题核心在于:Firestore安全规则会拒绝无过滤条件的全集合查询,因为规则无法批量验证每个文档的uidOwner是否匹配。需要同时调整规则和请求代码:
1. 更新Firestore规则
修改规则,同时支持单文档读取和带过滤条件的集合查询,还可以补充写入权限的校验:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /photos/{photo} { // 允许用户读取自己的文档:单文档读取或带uidOwner过滤的查询 allow read: if request.auth != null && (resource.data.uidOwner == request.auth.uid || request.query.where('uidOwner', '==', request.auth.uid)); // 确保只有用户自己能上传/修改属于自己的文档 allow write: if request.auth != null && request.resource.data.uidOwner == request.auth.uid; } } }
2. 修改iOS请求代码,添加查询过滤
在集合查询时必须带上uidOwner等于当前用户UID的过滤条件,这样规则才会允许查询执行:
func downloadImagesName(){ self.isLoading = true self.itemsPhoto = [] // 先确认用户已登录,获取当前用户UID guard let currentUserUID = Auth.auth().currentUser?.uid else { print("用户未登录,无法获取照片") self.isLoading = false return } // 添加过滤条件,只查询当前用户的照片 let imagesCollectionRef = db.collection("photos") .whereField("uidOwner", isEqualTo: currentUserUID) imagesCollectionRef.getDocuments(completion: { snapshot, error in if let error = error { print("Errore durante il recupero dei documenti: \(error.localizedDescription)") self.isLoading = false return } snapshot?.documents.forEach { doc in do { let item = try doc.data(as: Item.self) self.itemsPhoto.append(item) } catch { print("Errore durante la conversione dei dati: \(error.localizedDescription)") } } self.isLoading = false }) }
注意点
- 必须确保上传
Item到Firestore时,uidOwner字段确实被设置为当前登录用户的UID,否则即使规则和查询正确,也无法读取到文档。 - Firestore安全规则不会自动过滤不符合条件的文档,而是直接拒绝整个不符合规则的查询,所以查询必须携带对应的过滤条件。
内容的提问来源于stack exchange,提问作者matteog
相关产品推荐
相关产品推荐

