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

Swift中Firestore权限规则问题:用户无法访问自身数据

解决Firebase Firestore权限错误(Code=7)的方案

问题根源

你的Firestore规则要求用户只能访问文档ID等于自身UID的users集合文档,但当前代码存在两个核心问题:

  1. 创建用户数据时使用addDocument()生成随机文档ID,而非用户UID,导致规则中的request.auth.uid == userId(userId对应文档ID)不匹配。
  2. 获取用户数据时调用getDocuments()查询整个users集合,违反了规则中仅允许访问自身文档的限制。

修正步骤

1. 保持规则不变,调整数据结构

确保users集合的文档ID等于用户Firebase Auth的UID,你的规则逻辑本身是正确的,只需让数据结构匹配规则要求。

2. 修改Swift代码

创建用户数据(用UID作为文档ID)

func createUserData(userId: String, userEmail: String, completionHandler: @escaping (_ documentID: String?, _ userId: String?, _ userType: UserType?, _ tokensUsed: Int?) -> ()) {
    let db = Firestore.firestore()
    
    // 直接用用户UID作为文档ID,替代随机生成ID
    db.collection("users").document(userId).setData([
        "userEmail": userEmail,
        "lastLogin": Date(),
        "tokensUsed": 0,
        "userType": "free"
    ]) { error in
        if let error = error {
            print(error)
            completionHandler(nil, nil, nil, nil)
            return
        }
        // 直接通过UID获取数据,无需遍历集合
        self.getUserData(userId: userId) { documentID, userType, tokensUsed in
            completionHandler(documentID, userId, userType, tokensUsed)
        }
    }
}

获取用户数据(直接访问UID对应文档)

func getUserData(userId: String, completionHandler: @escaping (_ documentID: String?, _ userType: UserType?, _ tokensUsed: Int?) -> ()) {
    let db = Firestore.firestore()
    
    // 直接访问当前用户UID对应的文档,避免全集合查询
    db.collection("users").document(userId).getDocument { document, error in
        if let error = error {
            print(error)
            completionHandler(nil, nil, nil)
            return
        }
        guard let document = document, document.exists else {
            completionHandler(nil, nil, nil)
            return
        }
        
        let documentUserType = document["userType"] as? String ?? "free"
        let userType: UserType = documentUserType == "premium" ? .premium : .free
        let tokensUsed = document["tokensUsed"] as? Int ?? 0
        
        completionHandler(document.documentID, userType, tokensUsed)
    }
}

更新用户数据(操作当前用户的UID文档)

func updateUserData(userId: String, userEmail: String, userTokens: Int, userType: String) {
    let db = Firestore.firestore()
    
    // 直接通过UID更新文档,无需传入documentID
    db.collection("users").document(userId).updateData([
        "userEmail": userEmail,
        "lastLogin": Date(),
        "tokensUsed": userTokens,
        "userType": userType
    ]) { error in
        if let error = error {
            print(error)
        }
    }
}

3. 额外注意事项

  • 调用方法前,确保已通过Firebase Auth获取到有效用户UID(Auth.auth().currentUser?.uid),避免传入空值或错误ID。
  • 移除原代码中DispatchQueue.main.asyncAfter的超时逻辑,直接访问单个文档的响应速度足够快,无需超时兜底。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 15:30:21