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

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实例重复写逻辑:

  1. 拦截所有需要授权的请求;
  2. 检查accessToken是否过期,若过期则调用刷新接口获取新token;
  3. 将新token注入请求头或Cookie后转发请求。

方案2:滚动刷新机制

后端每次刷新accessToken时,返回新的refreshToken并设置新的httpOnly Cookie,避免旧refreshToken长期有效带来的安全风险。

方案3:客户端+服务端分层处理

  • 客户端用SWR/React Query的refreshInterval或onErrorRetry机制自动刷新token,适配页面数据实时更新场景;
  • 服务端敏感请求(如数据库操作)在Middleware中统一校验令牌,确保安全性。

内容的提问来源于stack exchange,提问作者adri.lh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 03:02:27