如何在Next.js服务器组件中实现Access与Refresh Token刷新?
在Next.js服务器组件中实现令牌刷新与请求重试
核心逻辑
当服务器组件向Express后端发起请求返回401时,执行以下流程:
- 调用后端的刷新令牌接口,携带当前的Refresh Token(从请求Cookie中获取)
- 若刷新成功,后端会返回新的Access Token和Refresh Token并通过
Set-Cookie设置 - 使用新的Cookie重新发起原请求
- 若刷新失败(比如Refresh Token也过期),返回未授权状态
具体实现
1. 封装带重试逻辑的请求函数
在服务器组件中封装通用请求工具,处理401重试逻辑:
import { headers } from 'next/headers'; // 限制重试次数,避免无限循环 const MAX_RETRY = 1; export async function fetchWithAuthRetry(url: string, options: RequestInit = {}) { const cookieHeader = headers().get('cookie'); let retryCount = 0; // 封装发起请求的内部函数 const makeRequest = async (currentCookie?: string) => { const requestHeaders = new Headers(options.headers); // 携带Cookie if (currentCookie) { requestHeaders.set('Cookie', currentCookie); } else if (cookieHeader) { requestHeaders.set('Cookie', cookieHeader); } const response = await fetch(url, { ...options, headers: requestHeaders, credentials: 'include', // 确保接收Set-Cookie }); if (!response.ok && response.status === 401 && retryCount < MAX_RETRY) { retryCount++; // 尝试刷新令牌 const newCookie = await refreshToken(); if (newCookie) { // 用新Cookie重试原请求 return makeRequest(newCookie); } } return response; }; return makeRequest(); }
2. 实现刷新令牌函数
调用后端刷新接口,提取响应头中的新Cookie:
async function refreshToken(): Promise<string | null> { const cookieHeader = headers().get('cookie'); const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/refresh-token`, { method: 'POST', headers: { ...(cookieHeader && { Cookie: cookieHeader }), }, credentials: 'include', }); if (!response.ok) { // 刷新失败,比如Refresh Token过期 return null; } // 从响应头中获取新的Set-Cookie值 const setCookieHeader = response.headers.get('set-cookie'); return setCookieHeader || null; }
3. 在服务器组件中使用工具函数
直接调用封装好的fetchWithAuthRetry即可自动处理401重试:
// 服务器组件示例 export default async function UserProfile() { const response = await fetchWithAuthRetry(`${process.env.NEXT_PUBLIC_API_URL}/api/user/profile`); if (!response.ok) { if (response.status === 401) { // 刷新也失败了,跳转到登录页或提示未授权 return <div>请重新登录</div>; } throw new Error('请求失败'); } const user = await response.json(); return <div>欢迎,{user.name}</div>; }
注意事项
- 重试次数限制:必须设置最大重试次数,避免因刷新接口也返回401导致无限循环
- Cookie处理:服务器组件无法直接访问浏览器
document.cookie,需通过headers()获取请求头中的Cookie并手动携带 - 跨域配置:若Express后端与Next.js不在同一域名,需配置CORS允许携带凭证(
credentials: true),且Access-Control-Allow-Origin需设为具体域名而非* - Refresh Token安全:刷新接口需仅接受POST请求,且验证Refresh Token有效性(如与数据库存储值比对)
内容的提问来源于stack exchange,提问作者David Mukopa
相关产品推荐
相关产品推荐

