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

Next.js服务端渲染中如何管理JWT?Axios调用API遇令牌问题求解

解决Next.js中Axios调用API的令牌处理与跨目录实例问题

一、服务端Axios拦截器无法获取令牌的解决方案

服务端渲染(SSR/SSG)时,无法直接访问localStorage,而Cookie可通过服务端请求头获取。需要区分客户端/服务端环境来处理令牌:

实现通用Axios实例创建函数

在项目根目录新建lib/axios.ts,编写适配两端环境的实例创建逻辑:

import axios from 'axios';
import { cookies } from 'next/headers';

const createAxiosInstance = (serverCookie?: string) => {
  const instance = axios.create({
    baseURL: process.env.NEXT_PUBLIC_API_BASE_URL,
    withCredentials: true, // 若用Cookie验证,需开启此选项
  });

  instance.interceptors.request.use((config) => {
    let token: string | undefined;

    // 服务端环境:从Cookie提取令牌
    if (typeof window === 'undefined') {
      if (serverCookie) {
        // 从传入的Cookie字符串中解析目标令牌(示例令牌Cookie名为auth_token)
        token = serverCookie.split('; ').find(row => row.startsWith('auth_token='))?.split('=')[1];
      } else {
        // 直接从Next.js的Cookie存储中读取(适用于App Router服务端组件)
        token = cookies().get('auth_token')?.value;
      }
    } else {
      // 客户端环境:从localStorage读取(若令牌存在localStorage中)
      token = localStorage.getItem('auth_token');
    }

    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  });

  return instance;
};

export default createAxiosInstance;

不同场景下的使用方式

  • 服务端组件/API路由:直接调用创建函数,自动从next/headers取Cookie
    import createAxiosInstance from '@/lib/axios';
    
    export default async function UsersPage() {
      const axios = createAxiosInstance();
      const { data: users } = await axios.get('/users');
      return <div>{users.map(u => <p key={u.id}>{u.name}</p>)}</div>;
    }
    
  • 客户端组件:直接调用创建函数,自动从localStorage取令牌
    'use client';
    import createAxiosInstance from '@/lib/axios';
    import { useEffect, useState } from 'react';
    
    export default function UserProfile() {
      const [profile, setProfile] = useState(null);
      const axios = createAxiosInstance();
    
      useEffect(() => {
        axios.get('/profile').then(res => setProfile(res.data));
      }, []);
    
      return <div>{profile?.name}</div>;
    }
    

二、跨目录复用Axios实例的解决方案

不要将Axios实例放在app/api目录下(该目录专为API路由设计,存在访问限制),而是将实例创建逻辑放在公共目录(如lib/utils),这样app和components目录都能通过绝对路径导入使用:

目录结构示例

your-project/
├── app/
│   └── users/
│       └── page.tsx
├── components/
│   └── UserCard.tsx
└── lib/
    └── axios.ts  # 公共Axios实例逻辑存放位置

在components目录中使用

'use client';
import createAxiosInstance from '@/lib/axios';

export default function UserCard({ userId }: { userId: string }) {
  const axios = createAxiosInstance();
  // 编写API调用逻辑
}

额外优化建议

如果后端支持通过HttpOnly Cookie验证身份,建议开启withCredentials: true,无需手动在请求头添加令牌:

  • HttpOnly Cookie无法被前端JS读取,能避免XSS攻击
  • Axios会自动在请求中携带Cookie,无需区分环境处理令牌

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 21:42:46