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; } }
验证步骤
- 执行登出操作,确认
PlayerDataSO的用户ID已被清空 - 重启游戏直接进入主菜单,点击读取按钮,应触发权限拒绝
- 登录后读取数据,登出后再次读取,确认权限拒绝逻辑正常
内容的提问来源于stack exchange,提问作者oetzi
相关产品推荐
相关产品推荐

