0

0

在Next.js Server Actions中删除Cookie的正确姿势

DDD

DDD

发布时间:2025-11-24 11:20:49

|

468人浏览过

|

来源于php中文网

原创

在next.js server actions中删除cookie的正确姿势

本文深入探讨了在Next.js应用中,使用next/headers模块通过Server Actions删除Cookie时可能遇到的问题及其解决方案。核心在于理解Server Components与Server Actions的执行上下文差异,并展示了如何通过将Server Action传递给Client Component并在客户端触发来成功删除Cookie,同时强调了相关的安全注意事项。

理解Next.js中Cookie删除的限制

在Next.js的App Router架构中,操作HTTP响应头(包括设置或删除Cookie)是一个敏感操作,必须在特定的上下文中执行。根据Next.js的官方文档,cookies().set()和cookies().delete()等方法只能在Server ActionsRoute Handlers中被调用。

当你在一个Server Component中定义一个带有"use server"指令的异步函数,并尝试直接在Server Component的渲染阶段调用它时,即使该函数本身是一个Server Action,其执行上下文也可能不被视为一个独立的Server Action调用。这意味着,直接在Server Component中调用cookies().delete()将导致运行时错误,提示“Cookies can only be modified in a Server Action or Route Handler”。

示例问题代码(错误用法):

// app/signout/page.js (Server Component)
import { cookies } from "next/headers";

export default async function Signout() {
    async function deleteTokens() {
       "use server" // 标记为Server Action

        cookies().delete('accessToken') // 在Server Component中直接调用,可能报错
    }

    // 在Server Component的渲染阶段直接调用
    await deleteTokens() 

    return (
        <>
    );
}

上述代码的问题在于,尽管deleteTokens被标记为Server Action,但它是在Server Component的初始渲染流程中直接调用的,而不是作为由客户端触发的独立Server Action。Next.js要求Server Actions必须由客户端交互(例如表单提交、按钮点击或通过useEffect等生命周期钩子)显式触发,才能正确修改响应头。

正确的解决方案:通过客户端组件触发Server Action

为了解决这个问题,我们需要将Server Action的调用逻辑从Server Component的渲染阶段分离出来,并通过一个Client Component来触发它。这种模式确保了Server Action在正确的上下文中执行,从而允许其修改Cookie。

核心思路:

Munch
Munch

AI营销分析工具,长视频中提取出最具吸引力的短片

下载
  1. 在Server Component中定义Server Action。
  2. 将这个Server Action作为prop传递给一个Client Component。
  3. 在Client Component中使用useEffect钩子来调用这个Server Action。

步骤一:在Server Component中定义并传递Server Action

首先,在你的Server Component(例如app/signout/page.js)中,像往常一样定义Server Action。然后,创建一个新的Client Component(例如SignOutAction.js),并将这个Server Action作为prop传递给它。

// app/signout/page.js (Server Component)
import { cookies } from "next/headers";
import SignOutAction from "./SignOutAction"; // 导入客户端组件

export default async function SignOut() {
  async function deleteTokens() {
    "use server"; // 明确标记为Server Action

    console.log("Attempting to delete accessToken cookie...");
    cookies().delete("accessToken"); // 在Server Action中删除Cookie
    console.log("accessToken cookie deletion attempted.");
  }

  // 将Server Action作为prop传递给Client Component
  return ;
}

步骤二:在Client Component中触发Server Action

接下来,在Client Component(例如app/signout/SignOutAction.js)中,使用"use client"指令将其标记为客户端组件。然后,利用useEffect钩子在组件挂载后(或在特定依赖项变化时)调用传入的Server Action。

为了确保Server Action函数在useEffect的依赖数组中保持稳定,即使父组件重新渲染,也可以使用useRef来存储并访问该函数。这可以避免不必要的useEffect重新执行。

// app/signout/SignOutAction.js (Client Component)
"use client";

import { useEffect, useRef } from "react";

export default function SignOutAction({ deleteTokens }) {
  // 使用useRef来确保deleteTokens函数引用的稳定性
  const deleteTokensRef = useRef(deleteTokens);

  // 在每次渲染时更新ref,以防deleteTokens函数本身发生变化
  useEffect(() => {
    deleteTokensRef.current = deleteTokens;
  });

  // 组件挂载后调用Server Action
  useEffect(() => {
    console.log("Client component mounted, calling deleteTokens action...");
    deleteTokensRef.current();
  }, []); // 空依赖数组确保只在组件挂载时执行一次

  // 此组件不需要渲染任何UI
  return null;
}

通过这种方式,deleteTokens函数作为一个真正的Server Action,在Client Component挂载后被触发。此时,Next.js会将其视为一个由客户端发起的请求,从而允许它在服务器端正确地修改响应头并删除Cookie。

注意事项与最佳实践

  1. Server Action的调用上下文: 再次强调,Server Actions的强大之处在于它们可以在客户端被调用,并在服务器上执行。但它们不能仅仅因为被定义在Server Component中,就在Server Component的渲染流程中拥有修改HTTP头的权限。它们需要一个客户端触发点。
  2. 安全性:CSRF防护: 当执行如注销(Sign Out)这样的敏感操作时,即使是简单的Cookie删除,也应考虑CSRF(跨站请求伪造)攻击的风险。直接在页面加载时通过useEffect触发注销操作,可能会使你的应用容易受到CSRF攻击。
    • 风险: 恶意网站可能嵌入一个指向你应用注销端点的隐藏请求(例如,一个在Next.js Server Actions中删除Cookie的正确姿势标签或一个自动提交的表单),当用户访问恶意网站时,就会自动触发你应用的注销操作,而用户毫不知情。
    • 建议: 对于注销、删除账户等操作,最佳实践是要求用户进行明确的交互,例如点击一个“注销”按钮,并且通常会结合CSRF令牌进行防护。这确保了请求是用户有意发起的,而不是被恶意网站劫持。
    • 虽然本教程解决了Cookie删除的技术问题,但在实际生产环境中,请务必为敏感操作添加CSRF防护。
  3. Next.js版本: 本文的解决方案适用于Next.js 13.4.4及更高版本,特别是使用App Router的场景。
  4. 用户体验: 对于注销等操作,通常会伴随页面重定向或状态更新,以向用户明确表示操作已完成。在deleteTokens Server Action执行完毕后,你可以考虑使用redirect函数(来自next/navigation)将用户重定向到登录页或其他合适页面。

总结

在Next.js中正确删除Cookie的关键在于理解Server Components和Server Actions的执行模型。虽然Server Actions允许在服务器端执行代码,但它们必须由客户端显式触发才能执行涉及HTTP响应头修改的操作。通过将Server Action作为prop传递给Client Component,并在Client Component的useEffect中调用它,可以有效地解决在Server Component中直接删除Cookie时遇到的问题。同时,务必牢记在设计敏感操作时,考虑并实施适当的安全措施,如CSRF防护。

相关专题

更多
cookie
cookie

Cookie 是一种在用户计算机上存储小型文本文件的技术,用于在用户与网站进行交互时收集和存储有关用户的信息。当用户访问一个网站时,网站会将一个包含特定信息的 Cookie 文件发送到用户的浏览器,浏览器会将该 Cookie 存储在用户的计算机上。之后,当用户再次访问该网站时,浏览器会向服务器发送 Cookie,服务器可以根据 Cookie 中的信息来识别用户、跟踪用户行为等。

6416

2023.06.30

document.cookie获取不到怎么解决
document.cookie获取不到怎么解决

document.cookie获取不到的解决办法:1、浏览器的隐私设置;2、Same-origin policy;3、HTTPOnly Cookie;4、JavaScript代码错误;5、Cookie不存在或过期等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

340

2023.11.23

阻止所有cookie什么意思
阻止所有cookie什么意思

阻止所有cookie意味着在浏览器中禁止接受和存储网站发送的cookie。阻止所有cookie可能会影响许多网站的使用体验,因为许多网站使用cookie来提供个性化服务、存储用户信息或跟踪用户行为。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

406

2024.02.23

cookie与session的区别
cookie与session的区别

本专题整合了cookie与session的区别和使用方法等相关内容,阅读专题下面的文章了解更详细的内容。

88

2025.08.19

数据库Delete用法
数据库Delete用法

数据库Delete用法:1、删除单条记录;2、删除多条记录;3、删除所有记录;4、删除特定条件的记录。更多关于数据库Delete的内容,大家可以访问下面的文章。

269

2023.11.13

drop和delete的区别
drop和delete的区别

drop和delete的区别:1、功能与用途;2、操作对象;3、可逆性;4、空间释放;5、执行速度与效率;6、与其他命令的交互;7、影响的持久性;8、语法和执行;9、触发器与约束;10、事务处理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

208

2023.12.29

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

510

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

244

2023.07.28

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

3

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 3.6万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.0万人学习

React核心原理新老生命周期精讲
React核心原理新老生命周期精讲

共12课时 | 1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号