iOS应用如何从Firebase获取用户专属数据并解决权限、数据拉取异常问题
问题根因与解决方案
两个问题分别由安全规则配置错误、iOS端查询逻辑不匹配两个原因导致,具体修复方案如下:
1. 新增数据权限不足问题修复
根因
你当前的安全规则写法是match /contacts/{creatorsID},要求contacts集合下的文档ID必须等于登录用户的UID,但你iOS端新增数据用的是addDocument()方法,该方法会自动生成随机字符串作为文档ID,和当前用户UID不匹配,直接触发权限校验失败。
另外你的业务逻辑是单个用户可以添加多个联系人,原有规则限制了一个用户只能在contacts下有一个文档,完全不符合业务需求。
安全规则修正
将安全规则调整为匹配contacts下所有文档,区分读写场景做校验,既保证权限安全,也符合单用户多联系人的业务需求:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /contacts/{contactDocId} { // 读操作:校验文档所属creatorsID为当前登录用户 allow read: if request.auth != null && resource.data.creatorsID == request.auth.uid; // 新建操作:校验写入的creatorsID为当前登录用户,防止越权创建他人数据 allow create: if request.auth != null && request.resource.data.creatorsID == request.auth.uid; // 修改/删除操作:校验原文档所属creatorsID为当前登录用户 allow update, delete: if request.auth != null && resource.data.creatorsID == request.auth.uid; } } }
2. 拉取到所有用户联系人问题修复
根因
Firebase安全规则不会自动对查询结果做过滤,只会直接拒绝不符合规则的查询。你当前的拉取代码直接监听整个contacts集合,没有加过滤条件,会直接返回所有有权限访问的文档,不符合只拉取当前用户数据的需求。
iOS拉取代码修正
给查询添加whereField过滤条件,只拉取creatorsID等于当前登录用户UID的文档:
func fetchData() { // 先校验当前用户已登录 guard let currentUid = Auth.auth().currentUser?.uid else { print("用户未登录") return } // 添加过滤条件,只拉取当前用户创建的联系人 db.collection("contacts") .whereField("creatorsID", isEqualTo: currentUid) .addSnapshotListener { (querySnapshot, error) in guard let documents = querySnapshot?.documents else { print("No documents: \(error?.localizedDescription ?? "未知错误")") return } self.contacts = documents.map { (queryDocumentSnapshot) -> Contact in let data = queryDocumentSnapshot.data() let name = data["name"] as? String ?? "" return Contact(name: name) } } }
3. 可选:新增代码优化
可以在新增数据前先校验用户登录状态,避免隐式的nil值写入:
func addData(name: String) { guard let currentUid = Auth.auth().currentUser?.uid else { print("用户未登录,无法添加数据") return } do { _ = try db.collection("contacts").addDocument(data: ["name": name, "creatorsID": currentUid]) } catch { print(error.localizedDescription) } }
内容的提问来源于stack exchange,提问作者user4150758
相关产品推荐
相关产品推荐

