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

Next.js App Router:如何在401响应时自动触发登出重定向

统一处理Next.js请求401自动重定向的方案

要在请求封装工具里统一处理401重定向,核心是区分服务端/客户端环境——Next.js里两者的重定向API完全不同,不能混用。下面分App Router(Next.js 13+)和Pages Router两种场景给出具体实现:

一、App Router(Next.js 13+)场景

1. 编写带401处理的fetch封装

直接在封装函数里判断环境,调用对应重定向逻辑:

import { redirect } from 'next/navigation';

export async function fetchWithAuth(url, options = {}) {
  const isServer = typeof window === 'undefined';
  const response = await fetch(url, {
    ...options,
    // 统一配置请求凭证、headers等,按需调整
    credentials: 'include',
    headers: {
      'Content-Type': 'application/json',
      ...options.headers,
    },
  });

  // 捕获401状态码
  if (response.status === 401) {
    if (isServer) {
      // 服务端组件:调用Next.js官方redirect函数,触发服务端重定向
      // 注:这个函数会抛出特殊错误,Next.js会自动处理重定向,无需额外catch
      redirect('/logout');
    } else {
      // 客户端组件:直接跳转,也可以用useRouter(需在客户端组件中使用)
      window.location.href = '/logout';
      // 若用客户端useRouter:
      // const router = useRouter();
      // router.push('/logout');
    }
    // 抛出错误终止后续逻辑
    throw new Error('未授权,正在跳转到登录页');
  }

  return response;
}

2. 服务端组件中使用

直接调用封装函数即可,无需手动检查状态码:

// 服务端组件示例
import { fetchWithAuth } from '@/utils/fetchWithAuth';

export default async function UserProfile() {
  // 请求返回401时会自动重定向到logout
  const userRes = await fetchWithAuth('/api/user/profile');
  const userData = await userRes.json();

  return <div>用户名:{userData.name}</div>;
}

3. 客户端组件中使用

客户端组件调用时,会自动触发客户端跳转:

'use client';
import { fetchWithAuth } from '@/utils/fetchWithAuth';
import { useState, useEffect } from 'react';

export default function UserDashboard() {
  const [userData, setUserData] = useState(null);

  useEffect(() => {
    fetchWithAuth('/api/user/dashboard')
      .then(res => res.json())
      .then(data => setUserData(data))
      .catch(err => console.log(err));
  }, []);

  return userData ? <div>仪表盘:{userData.stats}</div> : <div>加载中...</div>;
}

二、Pages Router(Next.js 12及更早)场景

Pages Router的服务端重定向依赖res对象或getServerSideProps返回值,封装时需做适配:

1. 编写带401处理的fetch封装

export async function fetchWithAuth(url, options = {}, res) {
  const isServer = typeof window === 'undefined';
  const response = await fetch(url, {
    ...options,
    credentials: 'include',
  });

  if (response.status === 401) {
    if (isServer && res) {
      // API路由或getServerSideProps中,用res对象重定向
      res.writeHead(302, { Location: '/logout' });
      res.end();
    } else if (isServer) {
      // getServerSideProps中,返回重定向对象
      return {
        redirect: {
          destination: '/logout',
          permanent: false,
        },
      };
    } else {
      // 客户端直接跳转
      window.location.href = '/logout';
    }
    throw new Error('未授权');
  }

  return response;
}

2. 在getServerSideProps中使用

export async function getServerSideProps(context) {
  try {
    const response = await fetchWithAuth('/api/user', {}, context.res);
    const userData = await response.json();
    return { props: { userData } };
  } catch (err) {
    // 若封装函数返回重定向对象,直接返回
    if (err.redirect) {
      return err.redirect;
    }
    return { props: {} };
  }
}

关键注意事项

  • 服务端绝对不能调用window相关API,环境判断typeof window === 'undefined'必须准确。
  • App Router服务端组件中,redirect函数通过抛出错误实现,调用后一定要抛出错误终止后续代码,避免逻辑混乱。
  • 若在API路由中处理401,服务端可直接返回new Response(null, { status: 401 })让客户端统一捕获,也可用对应重定向API直接跳转。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 08:43:14