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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 14:52:13