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

Unity Firebase RTDB安全规则异常:未登录/登出后仍可读取数据

问题分析与解决

你的问题核心是Firebase实时数据库客户端的本地缓存机制导致的随机权限绕过:当你之前登录并读取过目标数据后,客户端会缓存该数据;未登录时如果再次请求同一路径,客户端可能直接返回缓存内容,而不向服务器发起权限校验,就出现了场景3的异常。

另外,你的PlayerDataSO在未登录状态下仍然保留着之前登录用户的PlayerDBUserId,这让客户端能定位到缓存的路径,进一步触发这个问题。

具体解决方案

1. 读取数据时强制跳过缓存

修改TestReadDB方法,使用GetValueAsync的重载,指定强制从服务器获取数据并校验权限:

DataSnapshot snapshot = await DBreference.Child("users")
    .Child(playerData.PlayerDBUserId)
    .Child("levelPassed")
    .Child("easy")
    .GetValueAsync(DataServerPreference.ServerOnly); // 完全跳过缓存,走服务器权限校验

2. 登出/启动时重置PlayerDataSO的用户ID

在SignOut方法里清除用户标识,避免未登录时请求错误路径:

public void SignOut()
{
    fbAuth.SignOut();
    playerData.PlayerDBUserId = string.Empty; // 重置用户ID
    playerData.PlayerName = string.Empty;
    Debug.Log("Signed out");
}

同时在FirebaseManagerAuth的Awake方法里初始化重置,确保启动时是干净状态:

void Awake()
{
    InitializeFirebase();
    playerData.PlayerDBUserId = string.Empty; // 启动时清空用户ID
    // ... 单例逻辑
}

3. 补充顶层安全规则,封堵全局权限漏洞

当前规则仅定义了users/$user_id的权限,补充顶层规则明确禁止未授权的全局访问:

{
  "rules": {
    "users": {
      "$user_id": {
        ".read": "$user_id === auth.uid",
        ".write": "$user_id === auth.uid"
      }
    },
    // 全局默认禁止未授权访问
    ".read": false,
    ".write": false
  }
}

4. 监听Auth状态变化,动态控制数据访问

在FirebaseManagerAuth中添加Auth状态监听,精准控制数据访问时机:

private void InitializeFirebase()
{
    try
    {
        fbAuth = FirebaseAuth.DefaultInstance;
        // 添加状态监听
        fbAuth.StateChanged += AuthStateChanged;
        AuthStateChanged(this, null); // 初始化时触发一次状态检查
    }
    catch (Exception e)
    {
        Debug.LogError("Gotcha - AUTH! " + e.Message);
    }
    // ... 其他初始化逻辑
}

private void AuthStateChanged(object sender, EventArgs eventArgs)
{
    if (fbAuth.CurrentUser == null)
    {
        // 未登录状态:清空用户ID+可选清理缓存
        playerData.PlayerDBUserId = string.Empty;
        // 可选:重置数据库连接,清理缓存
        FirebaseDatabase.DefaultInstance.GoOffline();
        FirebaseDatabase.DefaultInstance.GoOnline();
    }
    else
    {
        // 登录状态:同步用户信息
        playerData.PlayerDBUserId = fbAuth.CurrentUser.UserId;
        playerData.PlayerName = fbAuth.CurrentUser.DisplayName;
    }
}

// 销毁时移除监听,避免内存泄漏
private void OnDestroy()
{
    if (fbAuth != null)
    {
        fbAuth.StateChanged -= AuthStateChanged;
    }
}

验证步骤

  1. 执行登出操作,确认PlayerDataSO的用户ID已被清空
  2. 重启游戏直接进入主菜单,点击读取按钮,应触发权限拒绝
  3. 登录后读取数据,登出后再次读取,确认权限拒绝逻辑正常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 05:52:00