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

Swift开发Firebase应用:多用户数据是否相互隔离?

问题分析与解决方案

结论:其他用户完全可以看到并修改所有用户添加的餐食,你的代码目前存在严重的数据隔离问题:

当前代码的核心问题

  • 所有用户读写的是Firebase数据库根节点下的meals和mealIngredients全局数组,没有做用户区分。任何用户添加的餐食都会混入同一个数组,所有用户加载数据时都会拿到全部内容。
  • 没有启用用户身份验证,也没有基于用户ID做数据隔离,默认规则下甚至匿名用户都能读写这些全局数据。

解决步骤

1. 启用Firebase身份验证

先在Firebase控制台启用至少一种身份验证方式(比如邮箱密码、匿名登录),确保每个用户有唯一的UID标识。

2. 重构数据结构

放弃全局数组,改为按用户UID存储个人餐食数据,推荐结构:

userMeals
  └── {用户UID}
      ├── meal1: {name: "番茄炒蛋", ingredients: "番茄、鸡蛋"}
      ├── meal2: {name: "红烧肉", ingredients: "五花肉、酱油"}

这种结构比分开存两个数组更合理,避免名称和配料对应出错,也能支持并发写操作(不会像数组那样被整体覆盖)。

3. 修改代码适配新结构

以下是修改后的核心代码示例:

import Foundation
import FirebaseDatabase
import FirebaseAuth
import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var mealNameField: UITextField!
    @IBOutlet weak var mealIngredientsField: UITextField!
    @IBOutlet weak var mealCountField: UITextField!
    @IBOutlet weak var mealPlanScrollView: UIScrollView!
    
    private let database = Database.database().reference()
    private var currentUserUID: String? {
        Auth.auth().currentUser?.uid
    }
    
    // 用字典存储餐食,key是Firebase生成的唯一ID,value是餐食信息
    var meals: [String: [String: String]] = [:]

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 先确保用户已登录,这里以匿名登录为例
        if Auth.auth().currentUser == nil {
            Auth.auth().signInAnonymously { [weak self] result, error in
                guard let self = self, error == nil else { return }
                self.loadUserMeals()
            }
        } else {
            loadUserMeals()
        }
    }
    
    private func loadUserMeals() {
        guard let uid = currentUserUID else { return }
        
        database.child("userMeals").child(uid).observe(.value) { [weak self] snapshot in
            guard let self = self, let mealDict = snapshot.value as? [String: [String: String]] else {
                self?.meals = [:]
                return
            }
            self.meals = mealDict
            // 这里更新UI展示餐食列表
        }
    }

    @IBAction func addMeal(_ sender: Any) {
        guard let uid = currentUserUID,
              let mealName = mealNameField.text, !mealName.isEmpty,
              let mealIngredients = mealIngredientsField.text, !mealIngredients.isEmpty else {
            return
        }
        
        // 生成唯一餐食ID,避免覆盖
        let mealRef = database.child("userMeals").child(uid).childByAutoId()
        let mealData = ["name": mealName, "ingredients": mealIngredients]
        mealRef.setValue(mealData)
        
        mealNameField.text = ""
        mealIngredientsField.text = ""
    }
}

4. 设置数据库安全规则

在Firebase控制台的数据库规则中,添加以下规则,确保用户只能访问自己的数据:

{
  "rules": {
    "userMeals": {
      "$uid": {
        ".read": "$uid === auth.uid",
        ".write": "$uid === auth.uid"
      }
    }
  }
}

额外说明

  • 匿名登录的用户如果卸载重装应用,会丢失之前的餐食数据,如果需要持久化,建议改用邮箱密码或其他可关联账号的登录方式。
  • 避免使用数组存储列表数据:Firebase的数组在并发写时容易出现覆盖问题,用childByAutoId()生成唯一ID的字典结构更稳定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 14:37:29