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

Next.js 14中Axios实例及API服务无法读取Cookie令牌

Next.js 14中Axios拦截器无法获取Cookie令牌的问题

核心原因

你的问题本质是Next.js 14的服务器/客户端组件渲染模式差异导致的:

  • StaffTable默认是服务器组件,在服务端执行时,js-cookie无法访问浏览器Cookie,所以Cookies.get('token')返回undefined
  • 强行将页面改为客户端组件后,又违反了Next.js规则:客户端组件不能是async函数

解决方案

方案1:服务器组件中用Next.js原生API获取Token(快速适配)

利用Next.js提供的服务器端cookies() API获取令牌,再传递给API服务:

  1. 修改staffAPIServices.ts,支持接收token参数:
import axiosInstance from '../../axios/axiosInstance';

export const getStaff = async (token?: string) => {
  try {
    const response = await axiosInstance.get('admin/staff', {
      headers: token ? { Authorization: `Bearer ${token}` } : {}
    });
    if (response.data.status) {
      return response?.data?.data?.staff;
    }
  } catch (err: unknown) {
    const errorString = err instanceof Error ? err.message : 'Unknown Error';
    return err;
  }
};
  1. 在StaffTable组件中获取并传递token:
import clsx from 'clsx';
import { getStaff } from '@/app/utils/services/staff/staffAPIServices';
import { cookies } from 'next/headers'; // 导入服务器端Cookie API

export default async function StaffTable({
  query,
  page,
}: {
  query: string;
  page: number;
}) {

  interface ItemType {
    id: number;
    name: string;
    email: string;
    email_verified_at: string;
    created_at: string;
    updated_at: string;
    deleted_at: string;
  }

  const token = cookies().get('token')?.value; // 服务器端获取token
  const staff = await getStaff(token);

  // 原组件JSX内容保持不变
  return (
    <div className="mt-6 flow-root">
      {/* ... 原表格代码 ... */}
    </div>
  );
}

方案2:客户端组件用数据获取库处理异步请求(适合交互场景)

如果组件需要用户交互,改成客户端组件,用SWR/React Query处理异步数据:

  1. 修改StaffTable为客户端组件,用SWR获取数据:
'use client';
import clsx from 'clsx';
import useSWR from 'swr';
import axiosInstance from '@/app/axios/axiosInstance';

// 定义数据获取函数
const fetchStaff = async () => {
  const response = await axiosInstance.get('admin/staff');
  if (response.data.status) {
    return response.data.data.staff;
  }
  throw new Error('Failed to fetch staff');
};

export default function StaffTable({
  query,
  page,
}: {
  query: string;
  page: number;
}) {

  interface ItemType {
    id: number;
    name: string;
    email: string;
    email_verified_at: string;
    created_at: string;
    updated_at: string;
    deleted_at: string;
  }

  const { data: staff, error } = useSWR('staff', fetchStaff);

  if (error) return <div>加载员工数据失败</div>;
  if (!staff) return <div>加载中...</div>;

  // 原组件JSX内容保持不变
  return (
    <div className="mt-6 flow-root">
      {/* ... 原表格代码 ... */}
    </div>
  );
}

此时axiosInstance.ts无需修改,客户端组件中js-cookie可正常访问浏览器Cookie。

方案3:API路由转发请求(生产环境推荐)

通过Next.js API路由作为中间层,在服务端处理授权逻辑,更安全且符合架构设计:

  1. 创建app/api/admin/staff/route.ts:
import { cookies } from 'next/headers';
import axios from 'axios';
import { NextResponse } from 'next/server';

export async function GET() {
  const token = cookies().get('token')?.value;
  if (!token) {
    return NextResponse.json({ status: false, message: '未授权' }, { status: 401 });
  }

  try {
    const response = await axios.get(`${process.env.NEXT_PUBLIC_CLIENT_URL}/admin/staff`, {
      headers: { Authorization: `Bearer ${token}` },
      withCredentials: true
    });
    return NextResponse.json(response.data);
  } catch (err) {
    return NextResponse.json({ status: false, message: '获取员工数据失败' }, { status: 500 });
  }
}
  1. 修改staffAPIServices.ts调用本地API路由:
export const getStaff = async () => {
  try {
    const response = await fetch('/api/admin/staff');
    const data = await response.json();
    if (data.status) {
      return data.data.staff;
    }
  } catch (err: unknown) {
    const errorString = err instanceof Error ? err.message : '未知错误';
    return err;
  }
};

这种方式下客户端无需处理token,所有授权逻辑在服务端完成,避免令牌暴露。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 18:10:39