Next.js服务端如何获取refreshToken Cookie并实现令牌刷新?
Next.js服务端Axios令牌刷新问题解决方案
1. 服务端正确获取refreshToken Cookie的方法
你拿不到refreshToken的核心原因是Cookie的路径限制:你的refreshToken Cookie路径设为/auth/updateAccessToken,而Next.js服务端的cookies() API只能获取当前请求路径有权访问的Cookie(比如当前服务端页面路径是/dashboard,就拿不到路径为/auth/updateAccessToken的Cookie)。
解决步骤:
- 调整refreshToken的Cookie路径为
/:后端在设置refreshToken Cookie时,把path参数改为/,这样全站所有路由的服务端代码都能通过cookies()获取到这个Cookie。这是最通用的方案,因为refreshToken通常需要全局可用。 - 确保Cookie的domain和SameSite设置正确:必须和前端同域,SameSite设为
Lax或Strict(根据你的跨域场景调整),否则服务端无法读取。 - 正确提取Cookie值:
cookieStore.get('refreshToken')返回的是一个包含name、value、path等属性的对象,你需要取value字段:const refreshTokenCookie = cookieStore.get('refreshToken') const refreshToken = refreshTokenCookie?.value // 正确提取值
2. 在Axios拦截器中自动带入Cookie到刷新请求
服务端的Axios实例没有浏览器的自动Cookie携带机制,需要手动将当前请求的Cookie注入到刷新请求的头中:
优化后的拦截器代码:
import axios from 'axios' import { cookies, redirect } from 'next/headers' const API_URL = process.env.NEXT_PUBLIC_EXPRESS_PATH const axiosInstanceServerSide = axios.create({ baseURL: API_URL, }) // 提前将当前请求的所有Cookie注入Axios实例默认头 const cookieStore = await cookies() const allCookies = cookieStore.getAll().map(cookie => `${cookie.name}=${cookie.value}`).join('; ') axiosInstanceServerSide.defaults.headers.Cookie = allCookies axiosInstanceServerSide.interceptors.response.use( response => response, async error => { const originalRequest = error.config if (error.response?.status === 401 && !originalRequest._retry && typeof window === 'undefined') { originalRequest._retry = true try { // 使用已注入Cookie的Axios实例发起刷新请求 const refreshResponse = await axiosInstanceServerSide.post('/auth/updateAccessToken', {}) // 更新原始请求的Authorization头,用新的accessToken const newAccessToken = refreshResponse.data.accessToken originalRequest.headers.Authorization = `Bearer ${newAccessToken}` return axiosInstanceServerSide(originalRequest) } catch (refreshError) { // 执行登出逻辑:清除Cookie并跳转登录页 cookieStore.delete('accessToken') cookieStore.delete('refreshToken') redirect('/login') } } return Promise.reject(error) } )
关键要点:
- 提前将当前请求的所有Cookie注入到Axios实例的默认
Cookie头,无需每次请求手动拼接。 - 后端的
/auth/updateAccessToken接口需要校验请求头中的Cookie里的refreshToken,而非依赖自动携带。 - 刷新成功后,务必更新原始请求的
Authorization头,避免重试时仍使用过期token。
3. 更合适的accessToken更新方式
方案1:Next.js Middleware统一处理
把令牌刷新逻辑从页面的Axios拦截器移到app/middleware.ts中,所有服务端、客户端请求都会被拦截,无需在每个Axios实例重复写逻辑:
- 拦截所有需要授权的请求;
- 检查accessToken是否过期,若过期则调用刷新接口获取新token;
- 将新token注入请求头或Cookie后转发请求。
方案2:滚动刷新机制
后端每次刷新accessToken时,返回新的refreshToken并设置新的httpOnly Cookie,避免旧refreshToken长期有效带来的安全风险。
方案3:客户端+服务端分层处理
- 客户端用SWR/React Query的
refreshInterval或onErrorRetry机制自动刷新token,适配页面数据实时更新场景; - 服务端敏感请求(如数据库操作)在Middleware中统一校验令牌,确保安全性。
内容的提问来源于stack exchange,提问作者adri.lh
相关产品推荐
相关产品推荐

