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取Cookieimport 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
相关产品推荐
相关产品推荐

