フリーランスWebエンジニア HTNCode

▲
  • HOME
  • ABOUT
  • SERVICE
  • ACHIEVEMENT
  • BLOG
  • CONTACT
  • githubIcon
  • twitterIcon
プライバシーポリシー
footerLogoImage

© HTNCode All Rights Reserved.

eyecatch

Next.js13.4でreCAPTCHA v3を導入

作成日時:2023年8月19日 23:24

更新日時:2023年8月19日 23:47

Next.js

Tutorial

はじめに

HTNCodeです。
今回、Next.js 13.4でreCAPTCHA v3を導入しましたのでメモ。
※かなり粗削りな実装をした気がするので、間違い等あれば、ぜひお問い合わせフォームよりご指摘いただけますと幸いです!

■HTNCode Official Site_お問い合わせフォーム
https://www.htncode.com/contact

 

reCAPTCHAとは、お問い合わせフォーム等を利用してbot による迷惑メールやスパム攻撃が行われることを防いでくれるGoogle提供サービスです。
自分たちに迷惑メール等が送られてくるならまだましなのですが、お問い合わせフォームって自動で受付完了メールとか送られますよね。
それを利用して、全然関係のない方にも大量に攻撃されちゃうわけです。これを防ぐことは、もはや必須のマナーですね。
 
■Google_reCAPTCHA
https://www.google.com/recaptcha/about/

 

reCAPTCHAを利用するにはまず登録が必要なので、
その辺は「あさくらーめん@フルスタックエンジニア」さんのブログをご参考ください。
今回私も参考にさせていただきました。ありがとうございます。


■Zenn_Next.jsのWEBサイトにreCAPTCHA(v3)を導入する(あさくらーめん@フルスタックエンジニア)
https://zenn.dev/angelecho/articles/daeb265bb3bf4b

  

ファイル構成

appディレクトリ配下は以下構成になっています(関係ないファイル等は省略)。

app
├api
│ └recaptcha
│   └route.ts
├contact
│   └page.tsx
│
└layout.tsx

 

react-google-recaptcha-v3をインストール

npm install --save react-google-recaptcha-v3

 

.env.localファイルで環境変数を定義

RECAPTCHA_SERVER_SECRET_KEY="シークレットキーを入力"

 

layout.tsxでコンポーネントをラップする

<GoogleReCaptchaProvider>を使って、コンポーネントをラップします。
layout.tsxでラップすることで、サイト全体でreCAPTCHAが働いてくれるようになります。
※関係のない記述部分は省略

"use client";
import { GoogleReCaptchaProvider } from "react-google-recaptcha-v3";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <GoogleReCaptchaProvider
      reCaptchaKey="ここにサイトキーを入力(envファイルでもOK")"
      language="ja"
    >
      <Component />
    </GoogleReCaptchaProvider>
  );
}

 

route.tsを定義する

app/api/recaptchaフォルダ内にroute.tsファイルを作成し、以下のように記述します。

import { NextResponse } from "next/server";

type Token = {
  token: string;
};

export async function POST(req: Request) {
  const data: Token = await req.json();
  const { token } = data;
  const serverSecretKey = `secret=${process.env.RECAPTCHA_SERVER_SECRET_KEY}&response=${token}`;
  const responce_recaptcha = await fetch(
    "https://www.google.com/recaptcha/api/siteverify",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
      },
      body: serverSecretKey,
    }
  );

  const responceJson_recaptcha = await responce_recaptcha.json();

  if (responceJson_recaptcha.success) {
    return NextResponse.json({ message: "success" });
  } else {
    return NextResponse.json({
      message: "error",
      error: "reCAPTCHA verificationに失敗しました。",
    });
  }
}

 

お問い合わせフォームの送信処理内に処理を実装

最後にお問い合わせフォームのcontact/page.tsxファイル内で、送信ボタンをクリックした際に実行される処理部分に追記をします。

reCAPTCHAがbotかどうかを判定し、レスポンスを返してくるので、その結果に応じて処理を分岐させます。

"use client";
import { NextPage } from "next";
import { useGoogleReCaptcha } from "react-google-recaptcha-v3";

const Contact: NextPage = () => {
  //reCAPTCHAの処理の関数定義
  const { executeRecaptcha } = useGoogleReCaptcha();

  return () => {
    //メール送信処理
    const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
      event.preventDefault();

      // reCAPTCHAからtokenを取得
      let token = "";
      if (executeRecaptcha) {
        token = await executeRecaptcha("contact");
      } else {
        alert("何らかのエラーが発生しました。再度お試しください。");
      }

      // サーバーへrecaptcha認証要求
      const responce_server = await fetch("/api/recaptcha", {
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          token,
        }),
        method: "POST",
      });

      // レスポンスが200の場合にのみ、メール送信処理を実行
      if (responce_server.status === 200) {
        //ここにメール送信の処理
      } else {
        //ここにエラー時の処理
      }
    };

    return
    //省略
  };
};

export default Contact;

 

おわりに

以上、reCAPTCHA v3の実装方法でした。

それではまた。

 

HTNCode