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

React中Firebase实时数据库权限规则问题及登录状态存储建议

问题概述

我在React应用中使用Firebase实时数据库与身份验证服务,采用邮箱/密码认证开发库存应用,数据库包含inventory、batches、unfinished三个主节点。登录功能通过signInWithEmailAndPassword实现,因页面频繁刷新,使用sessionStorage存储登录状态。目前存在两个核心问题:

  1. 设置的数据库规则(.read和.write为auth.uid != null)未生效,希望仅允许已认证用户读写数据库
  2. 寻求sessionStorage存储登录状态的优化建议

登录代码:

const handleSignIn = async (values) => {
    signInWithEmailAndPassword(
      auth,
      values.username,
      values.password
    )
      .then((userCredential) => {
        sessionStorage.setItem("user", values.username);
        sessionStorage.setItem(
          "login",
          true
        );

        const user = userCredential.user;

        history.push("/inv");
        setMsg(null);
      })
      .catch((error) => {
        setMsg("The Email or Password is Invalid");
        console.log(error);
      });
  };

数据库规则:

"rules": {
    ".read": "auth.uid != null",
    ".write": "auth.uid != null"
  }
}

解决方案

一、数据库规则不生效的排查与修复

1. 修正规则语法错误

你的规则代码末尾多了一个冗余的},导致规则解析失败直接失效。修正后的正确规则:

{
  "rules": {
    ".read": "auth.uid != null",
    ".write": "auth.uid != null"
  }
}

修改后需在Firebase控制台的「实时数据库 -> 规则」页面点击发布,确保新规则生效。

2. 同步Firebase Auth客户端状态

数据库规则依赖的是Firebase Auth客户端的身份状态,而非你手动存在sessionStorage的标记。页面刷新后,若未触发Firebase Auth重新验证,数据库请求时auth.uid会为null,导致规则判断失败。

在应用初始化(如App组件或路由守卫)中添加Auth状态监听,自动恢复用户身份:

import { useEffect } from 'react';
import { auth, onAuthStateChanged } from './firebase';

// 在App组件内添加
useEffect(() => {
  const unsubscribe = onAuthStateChanged(auth, (user) => {
    if (user) {
      // 同步状态到sessionStorage
      sessionStorage.setItem("login", "true");
      sessionStorage.setItem("user", user.email);
    } else {
      // 清空存储并跳转登录页
      sessionStorage.removeItem("login");
      sessionStorage.removeItem("user");
      history.push("/login");
    }
  });

  return () => unsubscribe(); // 组件卸载时取消监听
}, [history]);

3. 验证数据库请求前的Auth状态

发起数据库请求前,先确认auth.currentUser是否存在,避免无权限请求:

import { get, ref } from "firebase/database";
import { auth, database } from './firebase';

const fetchInventory = async () => {
  if (!auth.currentUser) {
    console.error("用户未认证,无法访问数据库");
    return;
  }
  const snapshot = await get(ref(database, 'inventory'));
  // 处理数据逻辑
};

二、sessionStorage存储登录状态的优化建议

1. 减少冗余存储,依赖Firebase Auth原生状态

不需要将用户名(邮箱)存入sessionStorage,直接通过auth.currentUser?.email即可获取。仅保留必要的登录标记,或完全依赖Firebase的Auth状态监听管理登录状态。

2. 用React Context统一管理登录状态

单独使用sessionStorage会导致状态更新无法同步到所有组件,建议创建Auth Context统一管理用户状态:

// AuthContext.js
import { createContext, useContext, useState, useEffect } from 'react';
import { auth, onAuthStateChanged } from './firebase';

const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
      setUser(currentUser);
      // 辅助存储标记,用于路由快速判断
      if (currentUser) {
        sessionStorage.setItem("isLoggedIn", "true");
      } else {
        sessionStorage.removeItem("isLoggedIn");
      }
    });
    return unsubscribe;
  }, []);

  return (
    <AuthContext.Provider value={{ user }}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => useContext(AuthContext);

组件中直接通过Hook获取状态,无需读取sessionStorage:

const { user } = useAuth();
if (!user) {
  // 未登录逻辑处理
}

3. 优化路由守卫逻辑

结合Auth Context和sessionStorage做路由拦截,兼顾可靠性与性能:

import { Navigate, useLocation } from 'react-router-dom';
import { useAuth } from './AuthContext';

const PrivateRoute = ({ children }) => {
  const { user } = useAuth();
  const location = useLocation();

  // 先通过sessionStorage快速判断,再等待Auth状态确认
  if (!user && sessionStorage.getItem("isLoggedIn") !== "true") {
    return <Navigate to="/login" state={{ from: location }} replace />;
  }

  return children;
};

4. 注意sessionStorage的局限性

sessionStorage仅在当前标签页有效,关闭标签页后会清空。若需要跨标签页共享登录状态,可改用localStorage,但需确保退出登录时主动清空:

// 退出登录时
const handleSignOut = () => {
  signOut(auth).then(() => {
    localStorage.removeItem("isLoggedIn");
    history.push("/login");
  });
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 05:25:30