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

React应用中如何安全地使用认证信息进行路由控制?

解决思路&方案

1. 别自己存UID到state,用Firebase Auth的原生状态监听

你现在靠本地state存UID判断登录状态,确实容易被篡改。直接用Firebase Auth提供的onAuthStateChanged监听用户状态,这个状态由Firebase维护,客户端没法篡改。替换原来的逻辑:

import { onAuthStateChanged } from "firebase/auth";
import { auth } from "./firebase-config";

const Login = () => {
  const [loginError, setLoginError] = useState();
  const navigate = useNavigate();

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      if (user) {
        // 登录成功直接跳转,不用存UID到state
        navigate("/dashboard");
      }
    });

    // 组件卸载时取消监听,避免内存泄漏
    return () => unsubscribe();
  }, [navigate]);

  const loginUserHandler = (email, password) => {
    signInWithEmailAndPassword(auth, email, password)
      .catch((error) => {
        setLoginError(fbAuthErrorCodeToString(error.code));
      });
  };

  // ... 其他组件内容
};

2. 给受保护路由加全局守卫

不管用户怎么折腾客户端状态,路由层面必须做真实校验。封装一个ProtectedRoute组件,每次进入路由前都检查Firebase的真实登录状态:

import { Navigate, Outlet } from "react-router-dom";
import { onAuthStateChanged } from "firebase/auth";
import { auth } from "./firebase-config";
import { useState, useEffect } from "react";

const ProtectedRoute = () => {
  const [isLoggedIn, setIsLoggedIn] = useState(null);

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      setIsLoggedIn(!!user);
    });

    return () => unsubscribe();
  }, []);

  // 加载中显示加载组件,避免白屏
  if (isLoggedIn === null) {
    return <div>加载中...</div>;
  }

  // 已登录就放行,未登录踢回登录页
  return isLoggedIn ? <Outlet /> : <Navigate to="/login" />;
};

然后在路由配置里用这个组件包裹所有需要保护的路由:

import { Routes, Route } from "react-router-dom";

function App() {
  return (
    <Routes>
      <Route path="/login" element={<Login />} />
      {/* 所有受保护路由都放在这个容器下 */}
      <Route element={<ProtectedRoute />}>
        <Route path="/dashboard" element={<Dashboard />} />
        {/* 其他需要权限的路由 */}
      </Route>
      {/* 无效路由直接跳登录页 */}
      <Route path="*" element={<Navigate to="/login" />} />
    </Routes>
  );
}

3. Firestore安全规则必须兜底

就算用户侥幸进入了路由,Firestore这边必须把好最后一关,确保只有对应UID的用户能访问自己的数据。配置这样的安全规则:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // 仅允许登录用户访问自己的用户文档
    match /users/{userId} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
    // 若有Dashboard相关集合,同理校验UID
    match /dashboard-content/{userId} {
      allow read: if request.auth != null && request.auth.uid == userId;
    }
  }
}

额外小技巧:别给未登录用户暴露路由信息

比如导航栏,只有用户登录后才显示Dashboard这类链接,避免用户猜测路由URI,从源头减少不必要的麻烦。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 01:07:44