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

Next.js 14中间件中外部API验证失败后如何正确删除Cookie

问题解答

1. 正确删除Cookie的方案

你的Cookie没被删除有两个核心原因:

  • 修改后的Response未被中间件返回:removeUser创建了带删除Cookie的Response,但只是调用函数却没把这个Response传递回中间件,中间件最终还是用默认的NextResponse.next(),导致Cookie修改不生效。
  • Cookie属性不匹配:删除Cookie时必须和原Cookie的path、domain、secure、httpOnly等属性完全一致,否则浏览器找不到对应Cookie,删除操作无效。

修改后的代码示例

中间件代码:

import { NextResponse } from 'next/server';
import { verifyUser } from '@/lib';

export async function middleware(request) {
  // 接收verifyUser返回的验证失败Response
  const authResponse = await verifyUser(request);
  // 若存在验证失败的Response,直接返回它
  if (authResponse) return authResponse;

  // 页面保护的中间件逻辑
  return NextResponse.next();
}

export const config = {
  matcher: ['/', '/dashboard', '/login'],
};

verifyUser与removeUser函数:

export async function verifyUser(request) {
  // 替换为你的API调用与token验证逻辑
  const data = await fetch('外部API地址', {
    headers: { Authorization: `Bearer ${request.cookies.get('netlify')?.value}` }
  }).then(res => res.json());

  if (!data.success) {
    console.log('验证失败,删除Cookie');
    // 返回带删除Cookie操作的Response
    return removeUser(request);
  }
  // 验证成功,返回undefined,中间件继续执行后续逻辑
}

function removeUser(request) {
  // 获取原Cookie属性,确保删除时完全匹配
  const existingCookie = request.cookies.get('netlify');
  // 若验证失败需跳转到登录页,可替换为NextResponse.redirect(new URL('/login', request.url))
  const response = NextResponse.next();

  response.cookies.set({
    name: 'netlify',
    value: '',
    expires: new Date(0),
    // 必须匹配原Cookie的核心属性,根据实际情况调整
    path: '/',
    domain: existingCookie?.domain,
    secure: process.env.NODE_ENV === 'production',
    httpOnly: true,
    sameSite: 'lax',
  });

  return response;
}

2. 更优的逻辑结构建议

(1)封装独立的Auth中间件模块

把验证、Cookie操作、错误处理逻辑封装成独立模块,让中间件代码更简洁易维护:

// lib/auth-middleware.js
import { NextResponse } from 'next/server';

export async function handleAuth(request) {
  const token = request.cookies.get('netlify')?.value;
  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  try {
    const data = await fetch('外部API地址', {
      headers: { Authorization: `Bearer ${token}` }
    }).then(res => res.json());

    if (!data.success) {
      return removeUser(request);
    }
    // 验证成功返回用户信息,供后续逻辑使用
    return { user: data.user };
  } catch (error) {
    // API调用失败时也删除Cookie并跳转
    console.error('验证API调用失败:', error);
    return removeUser(request);
  }
}

function removeUser(request) {
  const existingCookie = request.cookies.get('netlify');
  const response = NextResponse.redirect(new URL('/login', request.url));
  
  response.cookies.set({
    name: 'netlify',
    value: '',
    expires: new Date(0),
    path: '/',
    domain: existingCookie?.domain,
    secure: process.env.NODE_ENV === 'production',
    httpOnly: true,
    sameSite: 'lax',
  });

  return response;
}

然后在中间件中调用:

import { handleAuth } from '@/lib/auth-middleware';

export async function middleware(request) {
  const authResult = await handleAuth(request);
  // 若返回的是Response对象(验证失败),直接返回
  if (authResult instanceof NextResponse) {
    return authResult;
  }

  // 页面保护逻辑,比如传递用户信息到页面
  const response = NextResponse.next();
  response.headers.set('X-User-ID', authResult.user.id);
  return response;
}

(2)统一Cookie配置

把Cookie的公共属性抽成常量,避免重复代码,保证增删Cookie时属性一致:

// lib/cookie-config.js
export const BASE_COOKIE_OPTIONS = {
  path: '/',
  secure: process.env.NODE_ENV === 'production',
  httpOnly: true,
  sameSite: 'lax',
};

// 删除Cookie时使用
response.cookies.set({
  name: 'netlify',
  value: '',
  expires: new Date(0),
  ...BASE_COOKIE_OPTIONS,
  domain: existingCookie?.domain, // 按需添加
});

(3)链式处理多中间件逻辑

如果有多个中间件需求(如日志、权限细分),可以用链式调用组织,让逻辑更清晰:

export async function middleware(request) {
  // 先执行Auth校验
  const authResponse = await handleAuth(request);
  if (authResponse) return authResponse;

  // 再执行其他中间件逻辑,比如请求日志
  await logRequest(request);

  return NextResponse.next();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 12:27:45