Next.js 13页面缓存致Middleware与动态页面失效问题求助
Next.js 13 App目录下Middleware缓存问题:Token失效后仍可访问页面
问题背景
我基于Next.js 13 App目录开发,通过Cookie存储JWT,依赖Middleware校验用户认证状态与Token有效性。当前遇到页面自动缓存的问题:
- 首次访问
/home/chat时,Middleware正常触发,路由校验逻辑正常执行 - 再次返回该页面时,页面已被缓存,Middleware不再触发,即便用户Token失效,仍能直接访问页面,引发权限安全问题
已尝试的解决方案(均无效)
- 按官方文档要求,在页面中添加
export const dynamic = 'force-dynamic'或export const revalidate = 0,未改变缓存行为 - 官方文档说明调用
cookies()函数会自动将页面设为动态渲染状态,但实际页面仍保持缓存,页面内的console.log()仅在首次访问时打印 - 临时方案:在Server Components中引入客户端组件调用
router.refresh(),但破坏了单页应用的体验,不符合需求
相关代码
/home/chat页面代码
import { cookies } from "next/headers"; import Link from "next/link"; import styles from "@/styles/chatPage/ChatPage.module.css"; import ChatClient from "@/components/chatPage/ChatClient"; import Profile_Service from "@/services/Profile.service"; export default async function ChatPage() { let token: string | undefined; let myself: Profile & { avatar: Avatar }; console.log("chat page"); try { token = cookies().get("crunchy-token")?.value; if (!token) throw new Error("No token value"); const profilService = new Profile_Service(token); myself = await profilService.getProfileAndAvatar(); } catch (err) { console.log(err); return ( <div className={styles.error}> <h2>Oops... Something went wrong!</h2> <Link href="/home" className={styles.errorLink}> <p>Return to Home Page!</p> </Link> </div> ) } return ( <ChatClient token={token} myself={myself}/> ) }
Middleware代码
import { verifyAuth } from "@/lib/auth/auth"; import { NextRequest, NextResponse } from "next/server"; export async function middleware(req: NextRequest) { const crunchyToken = req.cookies.get("crunchy-token")?.value; const verifiedToken = crunchyToken && (await verifyAuth(crunchyToken).catch((err) => { console.log(err); })); const url = req.nextUrl; console.log(verifiedToken, url); if ( verifiedToken && verifiedToken.login && req.nextUrl.pathname === "/home/create" ) { return NextResponse.redirect(new URL("/home", req.url)); } if ( verifiedToken && !verifiedToken.login && req.nextUrl.pathname.startsWith("/home") && req.nextUrl.pathname !== "/home/create" ) { return NextResponse.redirect(new URL("/home/create", req.url)); } if (req.nextUrl.pathname === "/" && !verifiedToken) { return NextResponse.redirect(new URL("/welcome", req.url)); } if (req.nextUrl.pathname === "/" && verifiedToken) { return NextResponse.redirect(new URL("/home", req.url)); } if (req.nextUrl.pathname.startsWith("/welcome") && verifiedToken) { return NextResponse.redirect(new URL("/home", req.url)); } if (req.nextUrl.pathname.startsWith("/home") && !verifiedToken) { return NextResponse.redirect(new URL("/welcome", req.url)); } } export const config = { matcher: [ /* * Match all request paths except for the ones starting with: * - icon, images * - api (API routes) * - _next/static (static files) * - _next/image (image optimization files) * - favicon.ico (favicon file) */ '/((?!api|icon|images|_next/static|_next/image|favicon.ico).*)', ], };
verifyAuth函数代码
import { jwtVerify} from "jose"; export const verifyAuth = async (token: string) => { try { const verified = await jwtVerify( token, new TextEncoder().encode(process.env.JWT_SECRET), ); return verified.payload; } catch (error) { throw new Error('Your token has expired'); } }
核心诉求
- 确保每次访问页面时,Middleware都会触发,严格执行Token校验逻辑
- Server Components能通过Cookie中的Token获取用户数据,且每次访问都重新执行相关逻辑(而非仅初始编译时执行一次)
内容的提问来源于stack exchange,提问作者Baptiste
相关产品推荐
相关产品推荐

