如何将ReCaptcha实现到Nextjs联系表单中?

hyrbngr7  于 2023-05-06  发布在  其他
关注(0)|答案(1)|浏览(151)

所以我在一个投资组合的网站上工作,我有一个联系人的形式实现了我。我能够连接到SendGrid的电子邮件传输,但现在我担心垃圾邮件。我在网上到处寻找一个好的解决方案,但我似乎不能让ReCaptcha在我的项目中工作:(。有人可以帮助我,并解释我可以做得更好吗?
我试过ReCaptcha v2和v3,但都不好。客户端编程工作正常,就像它应该的那样,但问题是我似乎不能让它在服务器端工作。下面是我的代码。

import React, { useState, useRef } from "react";
import ReCAPTCHA from "react-google-recaptcha";

export default function Contact() {
  const [name, setName] = useState("");

  async function handleSubmit(e) {
    const formData = {};
    Array.from(e.currentTarget.elements).forEach((field) => {
      if (!field.name) return;
      formData[field.name] = field.value;
    });
    fetch("/api/email", {
      method: "post",
      body: JSON.stringify(formData),
    });

    alert(
      `Bedankt voor het sturen van een bericht ${name}! Ik zal spoedig contact met je opnemen.`
    );
  }

  return (
    <main className="bg-gradient-to-b from-black to-[#434343]" id="contact">
      <section>
        <div className="flex mt-5">
          <h2 className="mx-auto text-3xl font-bold">Contact</h2>
        </div>
        <div className="flex mt-5">
          <p className="mx-auto text-center text-gray-300">
            Neem gerust contact op voor vragen of andere verzoeken!
          </p>
        </div>
        <div className="grid ld:grid-cols-2 esd:grid-cols-1 sd:grid-cols-1">
          <div className="flex">
            <img
              src="/contact/mail.png"
              alt=""
              className="w-[75%] mx-auto my-auto"
            />
          </div>
          <div className="flex mx-32 esd:mx-5 mb-10">
            <form
              method="post"
              onSubmit={handleSubmit}
              className="mx-auto my-auto space-y-5"
            >
              <input
                type="text"
                name="naam"
                value={name}
                required
                onChange={(e) => setName(e.target.value)}
                className="w-full rounded-full p-2 border bg-white text-black"
                placeholder="Naam"
              />
              <input
                type="email"
                name="email"
                required
                className="w-full rounded-full p-2 border bg-white text-black"
                placeholder="Wat is je email?"
              />
              <textarea
                placeholder="Je vraag of verzoek..."
                name="bericht"
                required
                className="w-full h-40 rounded p-2 border bg-white text-black"
                maxLength={300}
              ></textarea>
              <input
                type="submit"
                className="bg-gradient-to-br from-orange-400 to-[#4ECDC4] p-2 rounded cursor-pointer"
              />
            </form>
          </div>
        </div>
      </section>
    </main>
  );
}
yzuktlbb

yzuktlbb1#

因为你有问题的后端侧。首先,确保在.env.local文件中有以下环境变量:

NEXT_PUBLIC_RECAPTCHA_SITE_KEY=<your-recaptcha-site-key>
RECAPTCHA_SECRET=<your-recaptcha-secret-key>

通过在pages/api文件夹中创建名为validateRecaptcha.js的新文件,在Next.js项目中创建新的API路由。在这个文件中,添加一个函数来用密钥验证reCAPTCHA响应密钥。这可以使用fetch函数向reCAPTCHA API发出POST请求来完成:

// pages/api/validateRecaptcha.js
export default async function handler(req, res) {
  const { recaptchaResponse } = req.body;
  const secretKey = process.env.RECAPTCHA_SECRET;

  const response = await fetch(
    `https://www.google.com/recaptcha/api/siteverify?secret=${secretKey}&response=${recaptchaResponse}`,
    {
      method: "POST",
    }
  );
  const data = await response.json();

  if (data.success) {
    res.status(200).json({ success: true });
  } else {
    res.status(400).json({ success: false });
  }
}

更新Contact组件中的handleSubmit函数,将reCAPTCHA响应密钥发送到API路由并检查响应:

async function handleSubmit(e) {
  e.preventDefault();
  const recaptchaResponse = await recaptchaRef.current.executeAsync();
  recaptchaRef.current.reset();

  // ...continue with your existing form data processing

  const response = await fetch("/api/validateRecaptcha", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ recaptchaResponse }),
  });

  if (response.ok) {
    // reCAPTCHA validation passed
    fetch("/api/email", {
      method: "post",
      body: JSON.stringify(formData),
    });
    alert(
      `Bedankt voor het sturen van een bericht \${name}! Ik zal spoedig contact met je opnemen.`
    );
  } else {
    // reCAPTCHA validation failed
    alert("reCAPTCHA validation failed. Please try again.");
  }
}

最后,确保在Contact组件中引用了ReCAPTCHA组件,并且sitekey属性设置为NEXT_PUBLIC_RECAPTCHA_SITE_KEY环境变量:

const recaptchaRef = useRef();

// ...

<ReCAPTCHA
  ref={recaptchaRef}
  sitekey={process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY}
/>

通过这些更改,您的服务器端reCAPTCHA验证现在应该可以正常工作。当表单被提交时,reCAPTCHA响应密钥将被发送到/api/validateRecaptcha API路由,该路由将使用reCAPTCHA密钥对其进行验证。如果验证成功,表单数据将像以前一样发送到/api/email API路由。
该解决方案使用reCAPTCHA v2 Invisible,但相同的方法可以应用于reCAPTCHA v3,只需进行一些微小的修改。

相关问题