Next.js中间件获取URL查询Token异常:多次输出且出现Null
解决Next.js中间件处理重置密码路由时因静态资源请求导致Token为空崩溃的问题
问题描述
我在做重置密码功能时,给用户邮箱发了带Token查询参数的链接(比如http://localhost:3000/auth/newPassword?token=xxx),想用中间件在用户访问该路由前验证Token有效性。但运行后发现中间件会三次打印请求URL,其中第二次请求是http://localhost:3000/_next/static/chunks/pages/auth/newPassword.js?ts=1667894719054——这个请求不带Token参数,导致获取到的Token为null,最终触发jsonwebtoken的verify方法报错,项目直接崩溃。
当前使用的中间件代码:
import { NextResponse, NextRequest } from "next/server"; import { verify } from "jsonwebtoken"; const secret = process.env.JWT_SECRET!; export default async function middleware(req: NextRequest) { const url = req.url; const token = await req.nextUrl.searchParams.get("token")!; const cookies = req.cookies; if (url.includes("/auth/newPassword")) { console.log(url); if (token === undefined) { return NextResponse.redirect("http://localhost:3000/auth/signin"); } try { verify(token, secret); return NextResponse.next(); } catch (e) { return NextResponse.redirect("http://localhost:3000/auth/signin"); } } }
解决方案
关键修改点:
- 过滤Next.js的静态资源请求,只对页面路由做Token验证
- 完善Token空值判断,同时避免非空断言引发的强制类型错误
修改后的中间件代码:
import { NextResponse, NextRequest } from "next/server"; import { verify } from "jsonwebtoken"; const secret = process.env.JWT_SECRET!; export default async function middleware(req: NextRequest) { const url = req.url; // 直接放行静态资源请求,不做Token验证 if (url.includes("_next/static/")) { return NextResponse.next(); } // 去掉不必要的await和非空断言,保留原始返回值 const token = req.nextUrl.searchParams.get("token"); if (url.includes("/auth/newPassword")) { console.log(url); // 同时处理token为null或undefined的情况 if (!token) { // 使用相对路径跳转,避免硬编码域名 return NextResponse.redirect(new URL("/auth/signin", req.url)); } try { verify(token, secret); return NextResponse.next(); } catch (e) { return NextResponse.redirect(new URL("/auth/signin", req.url)); } } // 其他路由直接放行 return NextResponse.next(); }
原因说明
- Next.js加载页面时会自动请求对应的静态chunk文件(
_next/static/chunks/下的JS),这些请求不会携带页面路由的查询参数,所以Token必然为空; - 原代码用了非空断言
!,强制把get("token")的结果当成非空值,当Token实际为null时,直接传入verify就会报错; - 原代码只判断了
token === undefined,但searchParams.get()在参数不存在时返回的是null,不是undefined,导致空值没被拦截。
内容的提问来源于stack exchange,提问作者Eilon Shamir
相关产品推荐
相关产品推荐

