You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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设置等操作。当前代码仅创建了响应对象,但未返回,导致中间件默认继续执行原请求逻辑,重定向完全不生效。

额外潜在问题:

  1. 验证通过时,错误地将Cookie设置到NextResponse.next()(继续当前请求的响应),而非重定向响应
  2. 未处理adminreq接口请求失败的情况,可能导致后续user.username读取报错
  3. 开发环境下设置secure: true的Cookie会被浏览器拒绝保存
  4. 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 };
  }
}

关键修改说明

  1. 返回响应对象:所有分支都明确返回NextResponse实例,确保重定向和Cookie设置生效
  2. Cookie绑定到重定向响应:将Cookie设置到redirectRes(重定向响应)而非NextResponse.next()
  3. 环境动态设置secure:根据生产/开发环境切换Cookie的secure属性,避免开发环境Cookie无法保存
  4. 增强错误处理:添加接口请求状态检查、错误分支处理,避免代码崩溃
  5. 添加Content-Type头:确保后端能正确解析JSON参数

内容的提问来源于stack exchange,提问作者code now

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 20:12:49