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

如何在Next.js 13(app目录)中基于Firebase认证用户条件渲染组件?

在Next.js 13 App目录中实现服务端Firebase认证内容保护

要在服务端渲染的组件中安全地根据用户认证状态渲染内容,核心思路是在服务端验证Firebase的ID Token,避免客户端逻辑带来的内容泄露问题。以下是具体实现步骤:

1. 初始化Firebase Admin SDK(服务端)

首先需要在服务端配置Firebase Admin,用于验证客户端传来的ID Token。

创建lib/firebase-admin.js文件:

import { initializeApp, getApps, cert } from 'firebase-admin/app';
import { getAuth } from 'firebase-admin/auth';

// 从环境变量读取服务账号配置(需提前将Firebase Admin服务账号JSON转成字符串存入环境变量)
const serviceAccount = JSON.parse(process.env.FIREBASE_ADMIN_SERVICE_ACCOUNT);

// 避免重复初始化SDK
if (!getApps().length) {
  initializeApp({
    credential: cert(serviceAccount),
  });
}

export const auth = getAuth();

2. 在服务端组件中验证用户身份

Next.js 13 App目录下的page.jsx默认是服务端组件,可以直接编写异步逻辑获取并验证认证状态:

修改app/page.jsx:

import { auth } from '@/lib/firebase-admin';
import { cookies } from 'next/headers';

export default async function Home() {
  const cookieStore = cookies();
  // 从Cookie中获取客户端存储的Firebase ID Token
  const idToken = cookieStore.get('firebase-id-token')?.value;

  let isAuthenticated = false;

  if (idToken) {
    try {
      // 服务端验证Token有效性(自动检查过期、签名等)
      await auth.verifyIdToken(idToken);
      isAuthenticated = true;
    } catch (err) {
      // Token无效或过期,标记为未认证
      isAuthenticated = false;
    }
  }

  return (
    <main>
      <h1>Hello World</h1>
      {/* 仅认证用户可见的内容 */}
      {isAuthenticated && (
        <p>This text should only be visible to authenticated users</p>
      )}
    </main>
  );
}

3. 客户端登录后同步Token到Cookie

客户端登录成功后,需要将Firebase的ID Token存入HttpOnly Cookie(防止XSS攻击),因为客户端无法直接设置HttpOnly Cookie,所以需要通过API路由处理:

客户端登录组件示例

import { getAuth, signInWithEmailAndPassword } from 'firebase/auth';
import { useRouter } from 'next/navigation';

export default function Login() {
  const router = useRouter();
  const auth = getAuth();

  const handleLogin = async (e) => {
    e.preventDefault();
    const email = e.target.email.value;
    const password = e.target.password.value;

    try {
      const userCredential = await signInWithEmailAndPassword(auth, email, password);
      // 获取当前用户的ID Token
      const idToken = await userCredential.user.getIdToken();

      // 调用API路由将Token存入Cookie
      await fetch('/api/set-token', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ idToken }),
      });

      // 刷新页面让服务端重新获取认证状态
      router.refresh();
    } catch (err) {
      console.error('登录失败:', err.message);
    }
  };

  return (
    <form onSubmit={handleLogin}>
      <input type="email" name="email" placeholder="邮箱" required />
      <input type="password" name="password" placeholder="密码" required />
      <button type="submit">登录</button>
    </form>
  );
}

创建API路由存储Cookie

创建app/api/set-token/route.js:

import { NextResponse } from 'next/server';

export async function POST(request) {
  const { idToken } = await request.json();
  // Token有效期默认1小时,和Firebase ID Token保持一致
  const expiresIn = 60 * 60;

  return NextResponse.json(
    { success: true },
    {
      headers: {
        'Set-Cookie': `firebase-id-token=${idToken}; Path=/; HttpOnly; Max-Age=${expiresIn}; ${process.env.NODE_ENV === 'production' ? 'Secure;' : ''} SameSite=Lax`,
      },
    }
  );
}

4. 登出逻辑(可选)

创建app/api/logout/route.js用于清除认证Cookie:

import { NextResponse } from 'next/server';

export async function POST() {
  return NextResponse.json(
    { success: true },
    {
      headers: {
        'Set-Cookie': 'firebase-id-token=; Path=/; HttpOnly; Max-Age=0; SameSite=Lax',
      },
    }
  );
}

客户端登出组件示例

import { getAuth, signOut } from 'firebase/auth';
import { useRouter } from 'next/navigation';

export default function Logout() {
  const router = useRouter();
  const auth = getAuth();

  const handleLogout = async () => {
    await signOut(auth);
    await fetch('/api/logout', { method: 'POST' });
    router.refresh();
  };

  return <button onClick={handleLogout}>登出</button>;
}

注意事项

  • 确保Firebase Admin服务账号的环境变量在生产环境中安全存储(不要提交到代码仓库)。
  • 生产环境下务必开启Cookie的Secure属性,确保仅在HTTPS传输。
  • 服务端验证Token时,Firebase Admin会自动处理签名验证、过期检查等,无需额外逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 12:40:21