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

Next.js 13.4中间件中如何用Fetch API携带Cookie实现授权?

在Next.js 13.4中间件里没法用Axios,改用Fetch API做授权时碰到Cookie发不出去的问题。知道Fetch默认不发Cookie,已经加了credentials: include选项,但还是没用。

下面是Next.js中间件代码:

import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
const getUserRole = async function () {
  try {
    const res = await fetch("http://localhost:8080/auth/me", {
      method: "GET",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },
      credentials: "include",
    });
    if (res && res.status === 200) {
      return res.json();
    } else {
      console.error("Request failed");
    }
  } catch (error) {
    console.error('Request to "auth/me" failed', error);
  }
};

export function middleware(request: NextRequest) {
  const path = request.nextUrl.pathname;
  const isPublicPath =
    path === "/auth/login" || path === "/auth/register" || path === "/";
  const token = request.cookies.get("access_token")?.value || "";

  if (isPublicPath && token && path !== "/") {
    return NextResponse.redirect(new URL("/", request.nextUrl));
  }

  if (!isPublicPath && !token) {
    return NextResponse.redirect(new URL("/auth/login", request.nextUrl));
  }

  if (!isPublicPath && token) {
    console.log("tokkk :", token);
    getUserRole().then((res: any) => {
      console.log("role ::", res);
    });
  }
}

export const config = {
  matcher: ["/", "/auth/login", "/auth/register", "/dashboard"],
};

Nest.js后端CORS配置:

app.enableCors({
  origin: 'http://localhost:3000',
  allowedHeaders: [
    'Content-Type',
    'Authorization',
    'X-Requested-With',
    'X-HTTP-Method-Override',
    'Content-Type',
    'Accept',
    'Observe',
    'Access-Control-Allow-Credentials',
    'Access-Control-Allow-Origin',
    'Access-Control-Allow-Headers',
  ],
  methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
  credentials: true,
});

解决方法

1. 核心问题:中间件运行在服务器端,无浏览器Cookie上下文

Next.js中间件是在服务器环境运行的,不是浏览器端。你加的credentials: include只对浏览器端Fetch生效,服务器端Fetch没有浏览器的Cookie存储上下文,自然没法自动携带Cookie。而你在中间件里拿到的token是从当前请求的Cookie中获取的,需要手动传给Fetch请求。

2. 修改Fetch请求,手动携带Cookie

把getUserRole改成接收token参数,手动设置Cookie请求头:

const getUserRole = async function (token: string) {
  try {
    const res = await fetch("http://localhost:8080/auth/me", {
      method: "GET",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
        // 手动将token放入Cookie请求头
        "Cookie": `access_token=${token}`
      },
      // 服务器端Fetch无需credentials选项,可删除
    });
    if (res && res.status === 200) {
      return res.json();
    } else {
      console.error("Request failed");
    }
  } catch (error) {
    console.error('Request to "auth/me" failed', error);
  }
};

然后在中间件调用时传入token:

if (!isPublicPath && token) {
  console.log("tokkk :", token);
  getUserRole(token).then((res: any) => {
    console.log("role ::", res);
  });
}

3. 优化Nest.js的CORS配置

你的CORS配置里allowedHeaders混入了响应头(比如Access-Control-Allow-Credentials),这些是服务器返回给浏览器的响应头,不需要放在允许的请求头列表里,可精简为:

app.enableCors({
  origin: 'http://localhost:3000',
  allowedHeaders: [
    'Content-Type',
    'Authorization',
    'X-Requested-With',
    'X-HTTP-Method-Override',
    'Accept',
    'Observe',
  ],
  methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
  credentials: true,
});

4. 检查Cookie的SameSite属性

如果后端设置access_token时,SameSite属性设为Strict或Lax,跨域场景下可能导致Cookie无法发送。建议后端设置Cookie时:

  • 优先用SameSite: 'Lax'(默认值,适配大部分场景)
  • 若需跨域第三方Cookie,设SameSite: 'None',但必须同时添加Secure: true(仅HTTPS环境生效)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 16:52:52