Next.js表单未用handleSubmit且不改action时,如何随验证码状态更新状态?
解决方案
要在不修改表单action的前提下,通过Cloudflare Turnstile的验证状态控制提交按钮,核心是利用Turnstile客户端的回调事件更新你的captcha状态,具体实现如下:
1. 安装依赖
首先安装Cloudflare官方的React Turnstile组件:
npm install @cloudflare/turnstile
2. 客户端代码修改
在你的表单组件中,通过Turnstile的回调函数更新状态,组件会自动在表单中注入验证所需的隐藏字段,无需手动处理:
import { useState } from 'react'; import Turnstile from '@cloudflare/turnstile'; export default function ContactForm() { const [captcha, setCaptcha] = useState('not_verified'); return ( <form action="/api/contact_form" method="POST"> {/* 你的其他表单输入字段 */} <Turnstile siteKey="替换为你的Cloudflare Turnstile站点密钥" // 验证成功时更新状态,启用按钮 onSuccess={() => setCaptcha('verified')} // 验证失败或过期时重置状态,禁用按钮 onError={() => setCaptcha('not_verified')} onExpire={() => setCaptcha('not_verified')} // 可选:设置主题、大小等样式 theme="light" size="normal" /> <button type="submit" disabled={captcha === 'not_verified'}> Send </button> </form> ); }
3. 后端API路由验证
别忘了在你的/api/contact_form路由中添加Turnstile token的验证逻辑,防止前端被绕过:
export default async function handler(req, res) { if (req.method !== 'POST') { return res.status(405).json({ error: '仅支持POST请求' }); } // 从表单数据中获取Turnstile的响应token const token = req.body['cf-turnstile-response']; if (!token) { return res.status(400).json({ error: '请完成验证码验证' }); } // 向Cloudflare验证token有效性 const verifyRes = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ secret: '替换为你的Cloudflare Turnstile密钥', response: token, remoteip: req.headers['x-forwarded-for'] || req.connection.remoteAddress, }), }); const verifyData = await verifyRes.json(); if (!verifyData.success) { return res.status(400).json({ error: '验证码验证失败,请重试' }); } // 这里执行你的发送邮件逻辑 // ... res.status(200).json({ message: '邮件发送成功' }); }
关键说明
- 无需修改表单
action:Turnstile组件会自动在表单中插入一个名为cf-turnstile-response的隐藏输入框,提交表单时会把验证token一起发送到你的API路由 - 状态控制:通过
onSuccess、onError、onExpire三个回调,精准控制captcha状态,确保用户未完成验证时按钮处于禁用状态 - 后端验证是必须的:前端状态控制只是提升用户体验,恶意用户可以绕过前端直接调用API,所以必须在后端验证Turnstile的token有效性
内容的提问来源于stack exchange,提问作者SzymonOwczarek
相关产品推荐
相关产品推荐

