Next.js中间件功能正常但无法实现路由重定向求助
Next.js登录验证后重定向失效问题排查与解决
问题描述
我在Next.js项目中遇到以下问题:中间件运行无报错,但登录验证后无法按预期跳转到对应路由。已排查无代码错误与异常,附上相关代码请求指导排查并解决该重定向问题。
相关代码
middleware.js
import { sign, verify } from "next-token"; import { NextResponse } from "next/server"; export async function middleware(req, res) { if (req.nextUrl.pathname.startsWith("/sdp") && req.method == "POST") { let admins = await adminreq(); let clientData = await req.formData(); let user = admins[0]; console.log(user.username, user.password); let uname = clientData.get("username"); let pwd = clientData.get("password"); console.log(uname, pwd); if (user.username === uname && user.password === pwd) { let jwt = await sign({ name: uname }, process.env.SECRET); console.log(jwt); let res = NextResponse.next(); res.cookies.set("jwt", jwt, { secure: true }); NextResponse.redirect(new URL("/dashboard", req.url)); } else { NextResponse.redirect(new URL("/sdp", req.url)); } } } async function adminreq() { try { let req = await fetch(process.env.API, { method: "POST", body: JSON.stringify({ admin: true, }), }); let res = await req.json(); return res.data; } catch (err) { return { error: true, message: err.message }; } }
sdp/page.js
export default function Login(){ return( <div className="container shadow-4 rounded mt-3 mb-3 p-3 border border-primary bg-gradient-to-r from-violet-200 to-pink-200 sm:w-100 md:w-80 lg:w-80"> <h1 className="h1 text-center w-100">Admin Login</h1><hr /> <form method="post" action="/sdp"> <label htmlFor="name">Username</label> <input type="text" name='username' id="name" className="form-control mb-2" /> <label htmlFor="pwd">Password</label> <input type="password" name='password' className="form-control mb-2" /> <button className="btn btn-primary rounded-pill bg-gradient-to-r from-indigo-400 to-cyan-400" type='submit'>Login</button> </form> </div> ) }
问题分析
核心问题是中间件没有返回创建的响应对象。Next.js Middleware要求必须明确返回NextResponse实例,才能触发重定向、Cookie设置等操作。当前代码仅创建了响应对象,但未返回,导致中间件默认继续执行原请求逻辑,重定向完全不生效。
额外潜在问题:
- 验证通过时,错误地将Cookie设置到
NextResponse.next()(继续当前请求的响应),而非重定向响应 - 未处理
adminreq接口请求失败的情况,可能导致后续user.username读取报错 - 开发环境下设置
secure: true的Cookie会被浏览器拒绝保存 adminreq的fetch请求未添加Content-Type头,后端可能无法正确解析JSON参数
修复方案
修改后的middleware.js代码如下:
import { sign, verify } from "next-token"; import { NextResponse } from "next/server"; export async function middleware(req) { if (req.nextUrl.pathname.startsWith("/sdp") && req.method === "POST") { let admins = await adminreq(); // 处理接口请求失败的情况 if (admins.error) { console.error(admins.message); return NextResponse.redirect(new URL("/sdp", req.url)); } let clientData = await req.formData(); let user = admins[0]; console.log(user.username, user.password); let uname = clientData.get("username"); let pwd = clientData.get("password"); console.log(uname, pwd); if (user.username === uname && user.password === pwd) { let jwt = await sign({ name: uname }, process.env.SECRET); console.log(jwt); // 创建重定向响应并绑定Cookie const redirectRes = NextResponse.redirect(new URL("/dashboard", req.url)); redirectRes.cookies.set("jwt", jwt, { secure: process.env.NODE_ENV === "production", // 开发环境禁用secure,否则Cookie无法生效 httpOnly: true, // 增强Cookie安全性,防止XSS窃取 path: "/" }); return redirectRes; } else { return NextResponse.redirect(new URL("/sdp", req.url)); } } // 非/sdp POST请求,返回默认响应 return NextResponse.next(); } async function adminreq() { try { let req = await fetch(process.env.API, { method: "POST", headers: { "Content-Type": "application/json" // 添加JSON解析头 }, body: JSON.stringify({ admin: true, }), }); // 检查HTTP响应状态 if (!req.ok) { throw new Error(`请求失败,状态码:${req.status}`); } let res = await req.json(); return res.data; } catch (err) { return { error: true, message: err.message }; } }
关键修改说明
- 返回响应对象:所有分支都明确返回
NextResponse实例,确保重定向和Cookie设置生效 - Cookie绑定到重定向响应:将Cookie设置到
redirectRes(重定向响应)而非NextResponse.next() - 环境动态设置secure:根据生产/开发环境切换Cookie的
secure属性,避免开发环境Cookie无法保存 - 增强错误处理:添加接口请求状态检查、错误分支处理,避免代码崩溃
- 添加Content-Type头:确保后端能正确解析JSON参数
内容的提问来源于stack exchange,提问作者code now
相关产品推荐
相关产品推荐

