在Next.js App Router应用中如何存储JWT Access Token?
关于JWT Access Token存储的问题(Next.js环境)
我有一个基于JWT认证的后端服务,登录时会在响应体返回Access Token,同时把Refresh Token存在Http-only Cookie里。我知道Refresh Token会自动附在每个请求上,但现在纠结Access Token的最优存储方式,目前遇到的限制是:
- 不能用Local Storage或Cookie
- 不想把整个页面设为
'use client' - 如果存在RAM里,用户刷新页面Token就丢了,得重新调用刷新接口拿新的
虽然可以把Access Token也存成Cookie,但总觉得应该有更简便的方案,以下是我目前的实现代码:
"use server" import { token } from "@/tokens" import { cookies } from "next/headers" export async function refreshToken() { const response: Response = await fetch( "http://localhost:8000/auth/refresh-token", { credentials: "include", method: "POST", headers: { Cookie: cookies().toString() }, } ) if (!response.ok) return const body = await response.json() if (!body.access_token) return token.token = body.access_token }
export async function authFetch(url: string, init?: RequestInit): Promise<Response> { return await fetch( url, { headers: { "Authorization": `Bearer ${token.token}`, ...init?.headers }, cache: "no-store" } ) }
推荐方案:服务器端自动处理Token刷新与携带
既然你不想用客户端存储、也不想依赖客户端组件,最简便的方式是让服务器端的请求工具自动完成Token刷新逻辑,彻底摆脱全局RAM存储的依赖:
- 重构
authFetch,每次发起业务请求前,先通过Refresh Token获取有效Access Token,直接注入请求头:
"use server" import { cookies } from "next/headers" async function getValidAccessToken(): Promise<string | null> { // 调用刷新接口获取最新Access Token const response = await fetch("http://localhost:8000/auth/refresh-token", { credentials: "include", method: "POST", headers: { Cookie: cookies().toString() }, }) if (!response.ok) return null const body = await response.json() return body.access_token || null } export async function authFetch(url: string, init?: RequestInit): Promise<Response> { const accessToken = await getValidAccessToken() if (!accessToken) { // Token刷新失败,可返回401或触发登录跳转逻辑 return new Response(null, { status: 401 }) } return await fetch(url, { headers: { "Authorization": `Bearer ${accessToken}`, ...init?.headers }, cache: "no-store" }) }
- 移除全局
token变量,所有业务请求统一通过authFetch发起——每次服务器端处理请求时,都会重新调用刷新接口获取有效Token,页面刷新后也不会出现Token丢失的问题。
方案优势
- 全程无需客户端存储,也不用设置
'use client',所有逻辑在服务器端完成 - 页面刷新后,请求会自动重新获取Token,无状态丢失风险
- 无需维护全局Token状态,减少代码复杂度
内容的提问来源于stack exchange,提问作者don dalladon
相关产品推荐
相关产品推荐

