Next.js14 App Router服务端Axios设置Cookie解决方案求助
问题背景
使用Next.js14 App Router + Axios构建项目,在服务端Axios拦截器中处理AccessToken过期逻辑:捕获401错误后通过RefreshToken获取新AccessToken,但Next.js14限制仅能在Server Action或路由处理器中修改Cookie,直接在拦截器中调用cookies().set()无效。尝试过重定向调用Server Action触发NEXT_REDIRECT错误,使用cookies-next库也未解决,希望保留服务端请求优势,不切换到页面路由或客户端Axios。
现有拦截器代码
instance.interceptors.response.use( (config) => config, async (error) => { //토큰 만료 에러 if (error.response.status === 401) { const newAccessToken = await getNewAccessToken(); if (newAccessToken) { error.config.headers.Authorization = `Bearer ${newAccessToken}`; cookies().set("accessToken", newAccessToken); return axios(error.config); } else { // logout } } return Promise.reject(error); }, );
解决方案
核心思路是将刷新Token+设置Cookie的逻辑封装到Server Action中,服务端Axios拦截器直接调用该Action完成操作,避免在拦截器中直接操作Cookie。
1. 封装刷新Token的Server Action
在app/actions/auth.actions.ts(或对应路径)中创建Server Action,统一处理Token刷新和Cookie设置:
'use server'; import { cookies } from 'next/headers'; export async function refreshAndSetAccessToken() { // 从Cookie获取RefreshToken const refreshToken = cookies().get('refreshToken')?.value; if (!refreshToken) return null; try { // 调用后端刷新Token接口 const response = await fetch(`${process.env.API_URL}/refresh-token`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ refreshToken }), }); if (!response.ok) throw new Error('Token刷新失败'); const { accessToken: newAccessToken } = await response.json(); // 将新AccessToken写入Cookie cookies().set('accessToken', newAccessToken, { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'strict', maxAge: 60 * 60 * 24, // 有效期1天,按需调整 }); return newAccessToken; } catch (err) { // 刷新失败,清除无效Cookie cookies().delete('accessToken'); cookies().delete('refreshToken'); return null; } }
2. 修改Axios拦截器调用Server Action
更新服务端Axios实例的拦截器,调用上述Server Action获取新Token并重试请求:
import { refreshAndSetAccessToken } from '@/app/actions/auth.actions'; import axios from 'axios'; const instance = axios.create({ baseURL: process.env.API_URL }); instance.interceptors.response.use( (res) => res, async (error) => { if (error.response?.status === 401) { // 调用Server Action刷新Token并设置Cookie const newAccessToken = await refreshAndSetAccessToken(); if (newAccessToken) { // 更新请求头的Authorization error.config.headers.Authorization = `Bearer ${newAccessToken}`; // 重试原请求 return instance(error.config); } else { // 刷新失败,执行登出逻辑(如在Server环境可调用redirect跳转到登录页) // redirect('/login'); } } return Promise.reject(error); }, ); export default instance;
关键说明
- Server Action是Next.js14允许操作Cookie的合法环境,直接调用不会触发
NEXT_REDIRECT错误(重定向仅适用于客户端跳转场景) - 拦截器仅负责错误捕获、调用Action获取Token、重试请求,所有Cookie操作都在Server Action中完成,符合Next.js规则
- 保留了服务端请求的性能优势,无需切换到客户端Axios
内容的提问来源于stack exchange,提问作者user24862332
相关产品推荐
相关产品推荐

