0

0

在Next.js Server Action中正确删除Cookie的教程

DDD

DDD

发布时间:2025-11-24 15:35:00

|

979人浏览过

|

来源于php中文网

原创

在Next.js Server Action中正确删除Cookie的教程

本文深入探讨了在next.js应用中,通过服务器组件使用`cookies().delete()`删除cookie时遇到的常见问题及其解决方案。核心在于理解服务器组件与服务器action的执行上下文差异。即使函数标记为`"use server"`,也需要通过客户端组件触发才能正确执行cookie删除操作,并强调了在登出等场景中应注意的csrf安全风险。

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

在Next.js的App Router架构中,管理Cookie是一项常见的任务。next/headers模块提供了cookies() API,允许我们在服务器端读取和修改Cookie。然而,在使用cookies().delete('cookieName')时,开发者可能会遇到一个常见的误区,即在服务器组件中直接调用此方法,即使函数内部已标记"use server",也可能导致错误:“Cookies can only be modified in a Server Action or Route Handler.”(Cookie只能在服务器Action或路由处理程序中修改)。

为什么会发生此错误?

尽管您的函数(例如deleteTokens)被标记为"use server",使其成为一个服务器Action,但问题的关键在于它的调用上下文。当一个服务器组件(如app/signout/page.js)直接在渲染流程中执行一个标记为"use server"的函数时,Next.js并不会将其视为一个“服务器Action的调用”,而仅仅是服务器组件渲染的一部分。服务器Action需要通过特定的机制来触发,例如从客户端组件通过onClick事件调用,或者在页面加载时由客户端组件主动发起。

简而言之,cookies().delete()要求其执行环境是一个明确的服务器Action调用或一个路由处理程序(Route Handler),而不是服务器组件的渲染生命周期。

解决方案:通过客户端组件触发服务器Action

要解决这个问题,我们需要将服务器Action的实际调用委托给一个客户端组件。这样,当客户端组件挂载并执行时,它会触发对服务器Action的调用,从而在正确的上下文中删除Cookie。

实现步骤

我们将通过两个文件来实现这一机制:一个服务器组件(app/signout/page.js)和一个客户端组件(app/signout/SignOutAction.js)。

步骤一:在服务器组件中定义并传递服务器Action

首先,在您的服务器组件中定义需要执行的服务器Action。这个Action将负责删除Cookie。然后,将这个Action作为props传递给一个客户端组件。

文件路径: app/signout/page.js

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

export default async function SignOut() {
  // 定义一个服务器Action,负责删除accessToken
  async function deleteTokens() {
    "use server"; // 明确标记为服务器Action
    cookies().delete("accessToken"); // 删除名为'accessToken'的Cookie
  }

  // 将服务器Action作为prop传递给客户端组件
  return ;
}

说明:

  • deleteTokens函数内部使用"use server"指令,将其定义为一个服务器Action。
  • SignOut服务器组件渲染SignOutAction客户端组件,并将deleteTokens服务器Action作为deleteTokens prop传递。

步骤二:在客户端组件中触发服务器Action

接下来,创建一个客户端组件。这个组件将接收服务器Action作为prop,并在其生命周期中(例如,在组件挂载后)调用这个Action。

文件路径: app/signout/SignOutAction.js

ClipDrop Relight
ClipDrop Relight

ClipDrop推出的AI图片图像打光工具

下载
// app/signout/SignOutAction.js
"use client"; // 明确标记为客户端组件

import { useEffect, useRef } from "react";

export default function SignOutAction({ deleteTokens }) {
  // 使用useRef来存储服务器Action的引用,确保即使组件重新渲染也能调用到最新的函数实例
  const deleteTokensRef = useRef(deleteTokens);

  // 在组件挂载或deleteTokens prop更新时,更新ref的current值
  useEffect(() => {
    deleteTokensRef.current = deleteTokens;
  }, [deleteTokens]); // 依赖项为deleteTokens,确保ref始终指向最新的函数

  // 在组件首次挂载时调用服务器Action
  useEffect(() => {
    deleteTokensRef.current(); // 调用通过prop传递的服务器Action
  }, []); // 空依赖数组确保只在组件挂载时执行一次

  // 客户端组件不需要渲染任何UI,因此返回null
  return null;
}

说明:

  • "use client"指令是必不可少的,它将此文件标记为一个客户端组件。
  • useEffect钩子与空依赖数组[]结合,确保deleteTokensRef.current()仅在组件首次挂载时执行一次。
  • useRef在此处用于确保即使deleteTokens函数由于父组件重新渲染而发生变化,我们也能始终调用到最新的函数实例。对于这种一次性调用场景,它提供了一层额外的健壮性。

通过以上两步,当用户访问/signout页面时,SignOut服务器组件会渲染SignOutAction。SignOutAction在客户端浏览器上挂载后,其useEffect钩子会触发对deleteTokens服务器Action的调用,从而成功删除accessToken Cookie。

注意事项与安全考量

CSRF(跨站请求伪造)漏洞风险

上述实现方案虽然解决了Cookie删除的技术问题,但在登出(Signout)这样的敏感操作中,直接在页面加载时通过GET请求触发登出操作(即通过客户端组件的useEffect调用)存在CSRF漏洞风险

为什么存在风险? 如果一个恶意网站诱导用户访问一个包含您网站登出URL的图片或链接,用户的浏览器会自动发送一个GET请求到您的登出端点。由于这个请求是在用户已登录的情况下发出的,并且GET请求通常没有CSRF令牌保护,用户的会话就会被意外终止。

推荐做法:

  • 使用POST请求: 登出操作应始终通过POST请求触发。
  • 添加CSRF保护: 对于所有修改状态的POST请求,包括登出,都应实施CSRF令牌保护。
  • 用户明确操作: 登出操作应由用户明确点击“登出”按钮来触发,而不是页面加载时自动执行。

例如,您可以在SignOutAction中渲染一个按钮,并在用户点击按钮时调用deleteTokens:

// app/signout/SignOutAction.js (改进版,更安全)
"use client";

export default function SignOutAction({ deleteTokens }) {
  const handleSignOut = async () => {
    await deleteTokens();
    // 登出成功后,可以重定向用户到登录页面或首页
    window.location.href = '/login'; 
  };

  return (
    

您确定要登出吗?

); }

这样,用户需要主动点击按钮才能触发登出,并且可以在deleteTokens服务器Action中添加CSRF令牌验证。

错误处理

在实际应用中,服务器Action内部的Cookie删除操作也可能失败(尽管这种情况不常见)。建议在deleteTokens函数中添加适当的错误处理机制,并在客户端组件中处理Action返回的结果或抛出的错误。

// app/signout/page.js (带错误处理的服务器Action)
import { cookies } from "next/headers";

export default async function SignOut() {
  async function deleteTokens() {
    "use server";
    try {
      cookies().delete("accessToken");
      return { success: true };
    } catch (error) {
      console.error("Failed to delete accessToken cookie:", error);
      return { success: false, error: "Failed to delete cookie" };
    }
  }
  // ... 传递给客户端组件
}

总结

在Next.js的App Router中,cookies().delete()必须在服务器Action或路由处理程序的特定上下文中执行。当您需要在页面加载时删除Cookie时,正确的模式是将服务器Action定义在服务器组件中,然后将其作为prop传递给一个客户端组件,由客户端组件在挂载后触发调用。同时,对于登出等敏感操作,务必考虑CSRF防护,并通过用户交互(如点击按钮)来触发,而非自动执行。

相关专题

更多
cookie
cookie

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

6415

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来提供个性化服务、存储用户信息或跟踪用户行为。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

405

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

Java 项目构建与依赖管理(Maven / Gradle)
Java 项目构建与依赖管理(Maven / Gradle)

本专题系统讲解 Java 项目构建与依赖管理的完整体系,重点覆盖 Maven 与 Gradle 的核心概念、项目生命周期、依赖冲突解决、多模块项目管理、构建加速与版本发布规范。通过真实项目结构示例,帮助学习者掌握 从零搭建、维护到发布 Java 工程的标准化流程,提升在实际团队开发中的工程能力与协作效率。

10

2026.01.12

热门下载

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

精品课程

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

共58课时 | 3.5万人学习

国外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号