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

Next.js 14中间件重定向异常:鉴权失败未跳转至登录页

问题分析与解决方案

核心原因

你遇到的问题是异步请求(fetch/Server Action)不会自动触发浏览器页面跳转:

  • Middleware返回的NextResponse.redirect()仅作用于当前的fetch请求本身,服务器会返回302状态码和目标URL,但浏览器不会自动跳转到该URL——因为这是后台异步请求,不是用户触发的页面级导航。
  • 控制台日志显示GET /auth/login 200是服务器成功处理了重定向请求,但客户端没有对这个响应做跳转处理,因此页面停留在原路由。

解决方案

1. 客户端fetch请求手动处理重定向

在发起fetch请求的客户端代码中,检查响应的redirected属性或状态码,手动触发页面跳转:

async function fetchProtectedResource() {
  const res = await fetch('/api/testurl/your-path', {
    credentials: 'include' // 必须携带cookie,否则Middleware无法鉴权
  });

  // 检测到重定向时手动跳转
  if (res.redirected) {
    window.location.href = res.url;
    return;
  }

  // 处理正常响应或其他错误
  if (!res.ok) {
    const error = await res.json();
    console.error('请求失败:', error);
    return;
  }

  const data = await res.json();
  // 处理业务数据
}

2. 针对API路由返回401而非重定向

修改Middleware逻辑,对API类请求返回401 Unauthorized状态码,让客户端更易处理:

export async function middleware(request: Request) {
  const cookies = request.headers.get('cookie');
  const isApiRequest = request.url.includes('/api/'); // 判断是否为API请求

  // 无cookie的情况
  if (!cookies) {
    if (isApiRequest) {
      return new NextResponse(JSON.stringify({ error: '未授权' }), { status: 401 });
    }
    return NextResponse.redirect(new URL('/auth/login', request.url));
  }

  // ... 其余鉴权逻辑保持不变 ...

  // 示例:在无accessToken时的处理
  if (!accessToken) {
    console.log('No access token found');
    if (isApiRequest) {
      return new NextResponse(JSON.stringify({ error: '未授权' }), { status: 401 });
    }
    const redirectUrl = new URL('/auth/login', request.url);
    console.log('Redirecting to:', redirectUrl.toString());
    return NextResponse.redirect(redirectUrl);
  }

  // ... 其余鉴权逻辑保持不变 ...
}

之后客户端可以捕获401状态码,再触发跳转:

async function fetchProtectedResource() {
  try {
    const res = await fetch('/api/testurl/your-path', { credentials: 'include' });
    if (res.status === 401) {
      window.location.href = '/auth/login';
      return;
    }
    // 处理正常响应
  } catch (err) {
    console.error(err);
  }
}

3. Server Action中处理鉴权跳转

如果使用Server Action,可以直接在Action内部捕获未授权情况,调用Next.js的redirect函数:

'use server';

import { redirect } from 'next/navigation';

export async function getProtectedData() {
  const res = await fetch('/api/testurl/your-path', {
    credentials: 'include',
    headers: { 'Content-Type': 'application/json' }
  });

  if (res.redirected || res.status === 401) {
    redirect('/auth/login');
  }

  if (!res.ok) {
    throw new Error('请求失败');
  }

  return res.json();
}

关键区别

  • 页面导航请求(直接输入URL、点击Link组件):Middleware的重定向会直接触发浏览器跳转,无需额外处理。
  • 异步请求(fetch/Server Action):必须通过客户端代码或Server Action主动处理跳转逻辑。

内容的提问来源于stack exchange,提问作者Vaclav Vlcek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 15:22:11