Next.js结合Express后端实现用户登录状态校验方案咨询
解决Next.js Middleware登录校验的三个核心问题
1. 修复Axios在Edge环境的适配错误
Next.js Middleware运行在Edge Runtime,Axios依赖的XHR/HTTP适配器不被支持,直接用原生fetch替代即可,无需额外依赖:
import { NextRequest, NextResponse } from 'next/server' export default async function middleware(req: NextRequest) { const loginPageUrl = new URL('/auth/login', req.nextUrl.origin) const apiBaseUrl = process.env.NEXT_PUBLIC_MAIN_API try { // 用fetch替代Axios,携带请求的Cookie(JWT存在Cookie中) const res = await fetch(`${apiBaseUrl}/auth/whoami`, { credentials: 'include', // 关键:携带当前请求的Cookie headers: { 'Content-Type': 'application/json', }, }) if (res.status === 401) { return NextResponse.redirect(loginPageUrl) } const data = await res.json() if (data.status !== 'success') { return NextResponse.redirect(loginPageUrl) } } catch (err) { // 处理接口调用失败的情况,比如后端宕机,默认跳登录页 return NextResponse.redirect(loginPageUrl) } } export const config = { matcher: [ '/((?!api|_next/static|_next/image|favicon.ico|auth).*)', '/', ], }
2. 优化登录校验的标准实现
你的整体架构(Next.js前端+Express后端处理Auth)是符合常规方案的,调整几个细节让实现更规范:
- Cookie配置:Express后端返回JWT Cookie时,务必设置
HttpOnly、Secure(生产环境)、SameSite: 'lax',防止XSS攻击,同时确保跨域场景下Cookie能正常携带。 - Middleware逻辑:优先通过HTTP状态码判断(比如401直接跳转),再处理响应体,减少不必要的JSON解析。
- 排除路径:当前的matcher规则已经排除了登录页和静态资源,保持即可,避免循环跳转。
3. 添加缓存机制减少后端请求
每次请求都调用whoami会增加后端压力,可通过以下方式优化:
方案1:利用Edge Runtime的缓存
在fetch请求中添加缓存策略,对校验结果做短期缓存(比如5分钟),适用于登录状态不会频繁变更的场景:
const res = await fetch(`${apiBaseUrl}/auth/whoami`, { credentials: 'include', headers: { 'Content-Type': 'application/json', }, next: { revalidate: 300 }, // Next.js 13+的缓存配置,300秒后重新校验 })
方案2:设置本地状态Cookie
在Middleware校验通过后,设置一个短期的非HttpOnly Cookie(比如is_logged_in=true),后续请求先检查这个Cookie,只有当Cookie不存在或过期时才调用后端接口:
// 先检查本地缓存Cookie const isLoggedIn = req.cookies.get('is_logged_in')?.value === 'true' if (!isLoggedIn) { // 调用后端whoami接口校验 const res = await fetch(`${apiBaseUrl}/auth/whoami`, { credentials: 'include' }) if (res.status !== 200) { return NextResponse.redirect(loginPageUrl) } // 设置缓存Cookie,有效期5分钟 const response = NextResponse.next() response.cookies.set('is_logged_in', 'true', { maxAge: 300, path: '/', sameSite: 'lax', }) return response } // 已登录,放行 return NextResponse.next()
注意:这个方案仅作为缓存优化,核心校验还是依赖后端的whoami接口,避免前端Cookie被篡改导致权限绕过。
内容的提问来源于stack exchange,提问作者Islam Y-
相关产品推荐
相关产品推荐

