ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

React Server Actions 安全最佳实践:像 API 路由一样在动作内部做认证与授权(Vercel React Best Practices 规则实战)

React Server Actions 安全最佳实践:像 API 路由一样在动作内部做认证与授权(Vercel React Best Practices 规则实战) 前端教程【免费下载链接】preguntas-entrevista-reactPreguntas típicas sobre React para entrevistas de trabajo ⚛️项目地址https://gitcode.com/gh_mirrors/pr/preguntas-entrevista-react点击查看免费下载导读Server Actions以use server标记的异步函数在 React 与 Next.js 中扮演着表单提交与数据变更的核心角色它们由 React 在服务端执行能够直接访问数据库、密钥与私有 SDK。本文以仓库中 Vercel React Best Practices 规则server-auth-actions为主体系统讲解为什么必须把 Server Actions 当作公开 API 端点来对待、为什么认证与授权校验必须写在每个 Action 内部并给出「输入校验 → 认证 → 授权 → 执行变更」的完整可运行代码示例帮助你写出无法被绕过鉴权的安全服务端变更。一、背景Server Actions 到底是什么在深入安全规则之前先明确 Server Actions 的本质。仓库中的面试问答文档 《¿Qué son las Server Actions y cómo se usan con formularios en React?》 给出了精确定义Server Actions 是用use server指令标记的函数React 在后端执行它们它们可以访问数据库、密钥secrets或私有 SDK它们能直接与表单和按钮集成无需手工创建 REST 端点提交表单时React 会序列化FormData在服务端执行动作再把响应返回客户端。一个最朴素的例子如下来源同上use server export async function createPost(formData) { const title formData.get(title) await db.post.create({ data: { title } }) } // 客户端组件中 (use client) import { createPost } from ./actions export function PostForm() { return ( form action{createPost} input nametitle / buttonPublicar/button /form ) }这里的关键转变在于表单的action属性不再指向一个 URL而是直接接收一个服务端函数。从开发体验看这是巨大便利——但安全模型也因此发生了根本变化这正是server-auth-actions规则要解决的隐患。二、核心安全认知Server Actions 是公开端点规则原文开门见山地强调Impact: CRITICAL防止对服务端变更的未授权访问Server Actions带有use server的函数与 API 路由一样会被暴露为公开端点。因此必须在每个 Server Action内部校验身份认证authentication与授权authorization不能只依赖中间件middleware、布局守卫layout guards或页面级检查——因为 Server Actions 可以被直接调用。这句话是整条规则的安全前提。你可能会想既然我的页面只在登录后可见那按钮提交的 Action 不也天然受保护吗答案是否定的。页面是否渲染、路由是否被中间件拦截与「这个函数端点是否可被直接调用」是两回事。任何掌握了函数引用与调用方式包括通过表单构造请求的客户端都可以绕过 UI 层直接触发服务端变更。这与「API 路由必须自行鉴权不能依赖页面」是同一个道理。仓库的编译版总文档 AGENTS.md 第 3.1 节AGENTS.md#L635-L723收录了与规则文件完全一致的内容并归入「Server-Side PerformanceHIGH」大类而 SKILL.md 中明确将其优先级标注为 CRITICAL足见该规则在所有服务端实践中的分量。三、错误示范没有任何认证检查的删除操作规则给出的反面示例非常直观use server export async function deleteUser(userId: string) { // Anyone can call this! No auth check await db.user.delete({ where: { id: userId } }) return { success: true } }这段代码的问题在于deleteUser是一个完整的、可被外部直接调用的服务端变更端点但它只依赖调用方传进来的userId既不验证「调用者是谁」也不验证「调用者是否有权删除该用户」。任何一个能触发该 Action 的客户端都可以删除任意用户。这里补上注释后的等效解读是任何能调用它的人都能删任何用户。这类「未鉴权变更」正是 CRITICAL 级别的危害——它直接导致服务端数据被未授权修改unauthorized mutations而不只是性能或体验问题。四、正确示范在 Action 内部完成认证与授权正确的做法是把校验放进函数体内作为执行变更前的必经关卡use server import { verifySession } from /lib/auth import { unauthorized } from /lib/errors export async function deleteUser(userId: string) { // Always check auth inside the action const session await verifySession() if (!session) { throw unauthorized(Must be logged in) } // Check authorization too if (session.user.role ! admin session.user.id ! userId) { throw unauthorized(Cannot delete other users) } await db.user.delete({ where: { id: userId } }) return { success: true } }逐段拆解这个模式先认证authentication通过verifySession()确认「你是谁」。会话不存在则直接抛错并终止执行再授权authorization确认「你是否被允许做这件事」。示例中的规则是只有admin角色或者被删除的用户就是本人session.user.id userId时才允许删除最后才执行变更所有守卫通过后才触碰数据库。这条「认证 → 授权 → 变更」的顺序至关重要任何一步失败都应立即中止不能让未授权请求有机会执行数据库操作。把检查放在 Action 内部而不是依赖 middleware 或 layout是因为 Action 端点可被直接调用——中间件只保护了「经过页面的路径」保护不了「直接打向函数的路径」。五、完整进阶示范输入校验 认证 授权 变更生产环境中服务端变更通常还伴随着不可信的客户端输入。规则给出的第三个示例把校验也纳入流水线形成一个四阶段模式use server import { verifySession } from /lib/auth import { z } from zod const updateProfileSchema z.object({ userId: z.string().uuid(), name: z.string().min(1).max(100), email: z.string().email() }) export async function updateProfile(data: unknown) { // Validate input first const validated updateProfileSchema.parse(data) // Then authenticate const session await verifySession() if (!session) { throw new Error(Unauthorized) } // Then authorize if (session.user.id ! validated.userId) { throw new Error(Can only update own profile) } // Finally perform the mutation await db.user.update({ where: { id: validated.userId }, data: { name: validated.name, email: validated.email } }) return { success: true } }这个示例补充了三个值得注意的细节输入校验最先执行data: unknown表明参数来自不可信来源先用 zod 的parse做结构校验与类型收窄。校验通过后得到的validated对象类型完整、字段确定后续认证与变更都基于它进行不要信任客户端传来的「身份」userId来自表单但判断「这是不是本人资料」依据的是服务端会话里的session.user.id而非客户端声称的身份。授权判断永远以服务端可信来源会话、token、角色为准校验、认证、授权、变更四者缺一不可且顺序固定先校验输入防止畸形数据进入后续逻辑再认证你是谁再授权你能做什么最后变更真正触碰数据。使用zod的z.string().uuid()、min/max长度限制、z.string().email()等约束是把「客户端可能提交任何值」这一事实转化为「服务端只接受合法值」的防线。你也可以用其他校验库如 valibot、joi或手写守卫关键是校验必须发生在服务端 Action 内部而不是依赖前端的required属性——前端校验只是体验优化服务端校验才是安全边界。六、把规则放回仓库上下文与表单工作流的衔接这条规则并非孤立存在它与仓库中 Server Actions 的正面用法文档形成了完整的「用法 安全」闭环正面用法见 《Server Actions 与表单》form action{createPost}提交时React 自动序列化FormData并在服务端执行安全要求见本文所述的server-auth-actions规则凡是能通过action{fn}接到表单上的函数都是可直接调用的公共端点。换句话说表单集成带来的便利无需手写 endpoint、自动序列化、服务端执行并不能豁免安全义务。把createPost挂到form action上就等于向所有能提交该表单或能直接调用该函数的客户端开放了一个写入端点——因此createPost体内必须像deleteUser、updateProfile一样依次完成校验、认证与授权。仓库中 quiz/qa 下的同名问答文件 也从侧面印证了这些要点Server Actions 是「标记use server在服务端执行的函数」Q1、正确指令是use server而非use client或server-onlyQ2、通过form action{createPost}连接Q3、可访问数据库/密钥/私有 SDKQ4。既然它们握着数据库与密钥就必须用本文的鉴权模式看守。七、落地检查清单与常见误区将规则落地为可执行的检查清单每个包含写操作create / update / delete的 Server Action 都以verifySession()之类的认证检查开头认证通过后再做基于角色的授权判断如session.user.role ! admin且非本人时拒绝任何从客户端传入的标识userId、postId 等都不被直接信任必须与会话中的身份比对使用zod等校验库对unknown入参做结构校验再进入后续流程抛错unauthorized(...)或new Error(...)即可中止执行不继续触碰数据库不要假设「页面可见 Action 安全」中间件与 layout 守卫只是补充防线。常见误区对照误区事实中间件能拦截所有请求中间件保护的是页面/路由路径Server Actions 端点可被直接调用中间件拦截不到页面做了登录校验就足够页面校验只在 UI 层生效不构成服务端函数的安全边界前端表单已做必填校验前端校验可被绕过服务端必须用zod等独立校验客户端传入的 userId 可以信任身份与权限必须以服务端会话为准客户端字段只能作为待校验数据只有「删除」类高危操作需要鉴权任何写操作包括更新自己的资料都需要认证 授权结语Server Actions 把「表单提交」与「服务端变更」无缝衔接让开发者无需再手写 API 端点但这份便利的代价是每一个 Action 都从诞生起就是一个公开端点。Vercel 这条 CRITICAL 级别的server-auth-actions规则给出了唯一稳妥的防御姿势——把认证与授权检查写进每个 Action 内部严格遵循「校验输入 → 认证身份 → 授权操作 → 执行变更」的顺序。本文的所有代码示例均可从仓库中的 规则原文、AGENTS.md 第 3.1 节 直接引用并可与 SKILL.md 中其余server-系列规则如server-serialization、server-cache-react组合阅读形成完整的服务端工程实践体系。赞分享前端教程【免费下载链接】preguntas-entrevista-reactPreguntas típicas sobre React para entrevistas de trabajo ⚛️项目地址https://gitcode.com/gh_mirrors/pr/preguntas-entrevista-react点击查看免费下载相关推荐QuickRecorder macOS 录屏工具教程从安装到第一次录制QuickRecorder macOS 录屏工具教程从安装到第一次录制 QuickRecorder 是一款基于系统 ScreenCapture Kit 开发的桌面应用音视频屏幕录制Sanity 仓库中的 Vercel React 规则像对待 API 路由一样为 Server Actions 做认证与鉴权Sanity 仓库中的 Vercel React 规则像对待 API 路由一样为 Server Actions 做认证与鉴权 在 Next.js App RoCMS前端Polar Web 实战像保护 API 路由一样为 Next.js Server Actions 做认证与鉴权Polar Web 实战像保护 API 路由一样为 Next.js Server Actions 做认证与鉴权 导读 本文讲解 Polar 前端代码库 cl后端前端金融科技上一篇N_m3u8DL-RE完全手册从安装到高级配置全攻略下一篇Jellium Desktop迷你模式设置自定义迷你界面外观创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表