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

Next.js 13 app目录下如何向服务器组件传递授权令牌?

在Next.js 13 App目录中传递JWT令牌到服务器组件

一、通过Cookie传递(适合服务器组件渲染时直接获取)

如果你需要服务器组件在页面初始渲染时就能拿到令牌,可以在客户端将令牌写入Cookie,服务器组件通过cookies()读取:

客户端设置Cookie

在客户端组件中,从Context获取令牌后,用document.cookie写入:

// 客户端组件(需加'use client'指令)
'use client';

import { useAuthContext } from '../contexts/AuthContext';
import { useEffect } from 'react';

export default function AuthCookieSetter() {
  const { token } = useAuthContext();

  useEffect(() => {
    if (token) {
      // 设置Cookie,配置path确保全站可读取,secure和sameSite提升安全性
      document.cookie = `authToken=${token}; path=/; secure; sameSite=strict`;
    } else {
      // 令牌失效时清除Cookie
      document.cookie = `authToken=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
    }
  }, [token]);

  return null; // 这个组件只负责设置Cookie,无需渲染内容
}

服务器组件读取Cookie

在服务器组件中,从next/headers导入cookies()获取令牌:

// 服务器组件(app/page.js)
import { cookies } from 'next/headers';

export default async function ProtectedPage() {
  const cookieStore = cookies();
  const authToken = cookieStore.get('authToken')?.value;

  if (!authToken) {
    return <div>未授权,请登录</div>;
  }

  // 使用令牌请求受保护的数据源
  const res = await fetch('https://your-api.com/protected-data', {
    headers: {
      Authorization: `Bearer ${authToken}`
    }
  });
  const data = await res.json();

  return <div>获取到的数据:{JSON.stringify(data)}</div>;
}

二、通过请求头传递(可控发送时机,推荐你的需求)

因为浏览器页面导航请求的头无法自定义,所以要通过客户端发起API请求的方式带令牌,服务器端在API路由中用headers()读取:

客户端发起带请求头的API请求

在客户端组件中,从Context拿到令牌后,用fetch请求API路由时携带授权头:

// 客户端组件(需加'use client'指令)
'use client';

import { useAuthContext } from '../contexts/AuthContext';
import { useState, useEffect } from 'react';

export default function DataFetcher() {
  const { token } = useAuthContext();
  const [protectedData, setProtectedData] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchProtectedData = async () => {
      if (!token) {
        setError('未获取到授权令牌');
        return;
      }

      try {
        const res = await fetch('/api/protected-data', {
          headers: {
            Authorization: `Bearer ${token}`
          }
        });

        if (!res.ok) throw new Error('请求失败');
        const data = await res.json();
        setProtectedData(data);
      } catch (err) {
        setError(err.message);
      }
    };

    fetchProtectedData();
  }, [token]);

  if (error) return <div>错误:{error}</div>;
  if (!protectedData) return <div>加载中...</div>;

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

API路由读取请求头

在app/api/protected-data/route.js中,用headers()获取授权头并处理:

// API路由(服务器端运行)
import { headers } from 'next/headers';

export async function GET() {
  const headersList = headers();
  const authHeader = headersList.get('authorization');
  const token = authHeader?.split(' ')[1]; // 提取Bearer后的令牌

  if (!token) {
    return new Response(JSON.stringify({ error: '未授权' }), { status: 401 });
  }

  // 用令牌请求后端服务
  const res = await fetch('https://your-api.com/protected-data', {
    headers: {
      Authorization: `Bearer ${token}`
    }
  });

  if (!res.ok) {
    return new Response(JSON.stringify({ error: '数据源请求失败' }), { status: res.status });
  }

  const data = await res.json();
  return new Response(JSON.stringify(data), { status: 200 });
}

关键注意点

  • headers()和cookies()只能在服务器组件或API路由中使用,不能在客户端组件调用。
  • 请求头方案仅适用于客户端主动发起的API请求,无法让服务器组件在页面初始渲染时直接拿到令牌(除非配合Cookie)。
  • Cookie方案会随所有请求自动发送,适合需要服务器组件在页面渲染阶段就获取令牌的场景,但要注意Cookie的安全配置(secure、sameSite、httpOnly可选,httpOnly的话客户端无法读取,更安全)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 19:48:17