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

Next.js 13客户端组件因token获取无法使用async/await的解决方案咨询

解决方案

1. 将Token存储在HttpOnly Cookie中(推荐)

把登录后的Token存在HttpOnly、Secure的Cookie里,服务器端可直接读取Cookie中的Token,无需在客户端通过useEffect获取,页面就能保持Server Component身份,直接用async/await发起后端请求。

实现步骤:

  • 后端登录接口设置HttpOnly Cookie:
    // Node.js后端登录接口示例
    res.cookie('auth_token', token, {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'strict',
      maxAge: 24 * 60 * 60 * 1000 // 1天有效期
    });
    
  • Next.js Server Component中读取Cookie并请求数据:
    // app/protected/page.tsx(Server Component)
    import { cookies } from 'next/headers';
    import { redirect } from 'next/navigation';
    
    export default async function ProtectedPage() {
      const cookieStore = cookies();
      const token = cookieStore.get('auth_token')?.value;
    
      if (!token) {
        redirect('/login');
      }
    
      const res = await fetch('http://your-backend/api/data', {
        headers: {
          Authorization: `Bearer ${token}`
        }
      });
      const data = await res.json();
    
      return <div>{JSON.stringify(data)}</div>;
    }
    

2. 拆分页面:Server Component + 局部客户端组件

如果Token必须存在客户端存储(比如localStorage),可将页面主体设为Server Component,只把需要Token请求数据的部分拆成独立客户端组件,页面大部分逻辑仍能使用async/await。

实现示例:

  • 页面主体(Server Component):
    // app/protected/page.tsx(Server Component)
    import ClientDataComponent from './ClientDataComponent';
    
    export default async function ProtectedPage() {
      // Server Component的异步逻辑
      const serverRes = await fetch('http://your-backend/api/public-data');
      const serverData = await serverRes.json();
      
      return (
        <div>
          <h1>受保护页面</h1>
          <p>服务器端数据:{JSON.stringify(serverData)}</p>
          {/* 引入客户端组件处理带Token的请求 */}
          <ClientDataComponent />
        </div>
      );
    }
    
  • 客户端组件(处理Token请求):
    // app/protected/ClientDataComponent.tsx(加'use client'指令)
    'use client';
    
    import { useEffect, useState } from 'react';
    
    export default function ClientDataComponent() {
      const [data, setData] = useState(null);
    
      useEffect(() => {
        async function fetchProtectedData() {
          const token = localStorage.getItem('auth_token');
          if (!token) return;
    
          const res = await fetch('http://your-backend/api/protected-data', {
            headers: {
              Authorization: `Bearer ${token}`
            }
          });
          const result = await res.json();
          setData(result);
        }
    
        fetchProtectedData();
      }, []);
    
      return data ? (
        <p>客户端受保护数据:{JSON.stringify(data)}</p>
      ) : (
        <p>加载中...</p>
      );
    }
    

3. 使用SWR/React Query管理客户端请求

用SWR或React Query在客户端组件中封装请求逻辑,自动处理Token获取和请求状态,页面主体仍可作为Server Component,仅在需要的地方引入客户端组件。

SWR示例:

// app/protected/ClientDataComponent.tsx
'use client';

import useSWR from 'swr';

const fetcher = async (url: string) => {
  const token = localStorage.getItem('auth_token');
  const res = await fetch(url, {
    headers: {
      Authorization: `Bearer ${token}`
    }
  });
  return res.json();
};

export default function ClientDataComponent() {
  const { data, error } = useSWR('http://your-backend/api/protected-data', fetcher);

  if (error) return <p>请求失败</p>;
  if (!data) return <p>加载中...</p>;

  return <p>受保护数据:{JSON.stringify(data)}</p>;
}

4. 用Middleware做权限前置校验

在Next.js Middleware中检查Token(从Cookie或请求头),提前拦截未登录请求并重定向到登录页,页面内无需再处理登录状态判断,专注于数据获取。

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const token = request.cookies.get('auth_token')?.value;

  if (!token && request.nextUrl.pathname.startsWith('/protected')) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: ['/protected/:path*'],
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 04:26:20