Firestore写入权限不足问题求助:图片上传后无法保存文档
问题场景
我尝试将图片上传至Firebase Storage,随后写入Firestore数据库,但遇到了权限不足的错误。
实现代码
Swift上传与写入函数
func storeMarketplaceItem() { guard let userId = Auth.auth().currentUser?.uid else { print("user not authenticated") return } let db = Firestore.firestore() let storage = Storage.storage() let storageRef = storage.reference(forURL: "gs://garbage-separator.firebasestorage.app") //let storageRef = Storage.storage().reference() var uploadedImageURLs: [String] = [] let dispatchGroup = DispatchGroup() let imageID = UUID().uuidString for image in selectedImages { dispatchGroup.enter() //let imageID = UUID().uuidString let imageRef = storageRef.child("marketplace/\(imageID).jpg") // Metadata with userId for Firebase Storage let metadata = StorageMetadata() metadata.contentType = "image/jpeg" // Set content type for the image metadata.customMetadata = ["userId": userId] //metadata.customMetadata = ["ImageId": imageID] if let imageData = image.jpegData(compressionQuality: 0.5) { print("Uploading image to: marketplace/\(imageID).jpg") // Upload image to Firebase Storage imageRef.putData(imageData, metadata: metadata) { metadata, error in if let error = error { print("Image upload error: \(error.localizedDescription)") dispatchGroup.leave() return } // Fetch the download URL of the uploaded image imageRef.downloadURL { url, error in if let error = error { print("Failed to get URL: \(error.localizedDescription)") } else if let url = url { uploadedImageURLs.append(url.absoluteString) print("Image uploaded successfully: \(url.absoluteString)") } dispatchGroup.leave() } } } else { print("Image data conversion failed for image: \(imageID)") dispatchGroup.leave() } } // Ensure images are uploaded before saving to Firestore dispatchGroup.notify(queue: .main) { if uploadedImageURLs.isEmpty { print("No images uploaded, aborting item storage.") return } // Create a new item to save in Firestore let newItem = MarketItem(id: UUID().uuidString, name: name, description: description, price: price, imageURLs: uploadedImageURLs) var newItemData = [ "id": newItem.id, "name": newItem.name, "description": newItem.description, "price": newItem.price, "imageURLs": newItem.imageURLs, "userId": Auth.auth().currentUser?.uid ?? "" ] let documentId = newItem.id print("Generated Document ID: \(documentId)") let itemRef = db.collection("marketplace").document(imageID) itemRef.getDocument { (document, error) in if let document = document, document.exists { print("Document already exists.") } else { // Document doesn't exist, proceed with saving the new item itemRef.setData(newItemData) { error in if let error = error { print("Error saving item to Firestore: \(error.localizedDescription)") } else { print("Item successfully saved to Firestore!") presentationMode.wrappedValue.dismiss() } } } } // Add userId to Firestore document data // Save item to Firestore } } }
Firestore安全规则
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // Allow read and write access to all documents for authenticated users match /users/{userId} { allow read, write: if request.auth != null && request.auth.uid == userId; // Allow access to the "uploadCounts" subcollection match /uploadCounts/{documentId} { allow read, write: if request.auth != null && request.auth.uid == userId; } // Allow read access to anyone match /marketplace/{documentId} { allow read, write: if request.auth != null; //&& request.auth.uid == request.resource.data.userId; } } } }
错误信息
上传图片至:marketplace/98F348B5-5A95-43F0-A707-6782866F969B.jpg
图片上传成功:
marketplace%2F98F348B5-5A95-43F0-A707-6782866F969B.jpg?alt=media&token=4bb04ed4-8c3b-4814-810e-012e88ab03e1
生成的文档ID:9FA8CA52-5971-4A11-90FF-900F521F7644
10.29.0 - [FirebaseFirestore][I-FST000001] 监听marketplace/98F348B5-5A95-43F0-A707-6782866F969B查询失败:权限缺失或不足。
保存条目至Firestore时出错:权限缺失或不足。
10.29.0 - [FirebaseFirestore][I-FST000001] (null)
10.29.0 - [FirebaseFirestore][I-FST000001] 写入marketplace/98F348B5-5A95-43F0-A707-6782866F969B失败:权限缺失或不足。
10.29.0 - [FirebaseFirestore][I-FST000001] (null)
问题原因与解决方法
核心问题:安全规则层级错误
你的marketplace集合规则被嵌套在/users/{userId}的匹配规则内,Firestore会默认认为marketplace是users集合下的子集合,但实际代码中你是直接访问根级的marketplace集合,导致规则不匹配,触发权限验证失败。
修复步骤
- 调整安全规则结构,将
marketplace规则移至users规则外部,作为根级集合规则:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // 用户集合规则 match /users/{userId} { allow read, write: if request.auth != null && request.auth.uid == userId; // 用户下的uploadCounts子集合规则 match /uploadCounts/{documentId} { allow read, write: if request.auth != null && request.auth.uid == userId; } } // 根级marketplace集合规则 match /marketplace/{documentId} { allow read, write: if request.auth != null; } } }
- 可选优化:文档ID一致性
代码中生成了newItem.id作为文档ID,但实际写入时用的是imageID,导致日志显示的文档ID与实际写入ID不一致(虽非权限错误原因,但易引发后续逻辑混乱),建议统一:
将let itemRef = db.collection("marketplace").document(imageID)修改为let itemRef = db.collection("marketplace").document(documentId)。
内容的提问来源于stack exchange,提问作者sats

