/

WordPressでreCaptcha v3の実装

WordPressでreCaptcha v3の実装

WordPressでreCaptchaを実装する方法を紹介したいと思います。

v3なのでreCaptchaでよく見るチェックするタイプのものではありません。スコア判定するものです。

WordPressでもそうでなくても基本的には一緒なのでですが、script分離したかったので、Wordpressでということにしています。

今回は自作したログイン画面を想定したreCpatcha設定です。

HTML側の設定

<form id="register-form" action="<?php echo wp_registration_url(); ?>" method="post">

    <div>
        <label for="mail">メールアドレス</label>
        <input name="register_mail" type="text" id="mail" required>
    </div>
    <div>
        <label for="password">パスワード</label>
        <input name="register_pass" type="password" id="password" required>
    </div>

    <p><?php echo wp_get_password_hint(); ?></p>

    <div>
        <input type="submit" name="register_submit" id="submit-button" value="登録" />
        <?php wp_nonce_field( 'register_login_nonce', 'register_login_nonce_field' ); ?>
    </div>

</form>

メールアドレスとパスワードを入力させて、その値でユーザー登録を行うものです。

reCpatcha用のフィールドはスクリプトで埋め込んでいきますので、この段階では特にreCpatchaらしいところはないです。

javaScriptの設定

window.addEventListener( 'DOMContentLoaded', () => {
    reCaptcha();
} );

const reCaptcha = () => {
    const form = document.querySelector( '#register-form' );
    const submitButton = form.querySelector( '#register_submit' );

    if ( ! form || ! submitButton ) return false;

    submitButton.addEventListener( 'click', ( e ) => {
        e.preventDefault();
        grecaptcha.execute( frontData['sitekey'], { action: "register" } )
        .then( token => {
            const input = document.createElement( 'input' );
            
            input.setAttribute( 'type', 'hidden' );
            input.setAttribute( 'name', 'g-recaptcha-response' );
            input.setAttribute( 'value', token );
            
            form.appendChild( input );
            form.submit();
        } );
    } );

};

reCaptchaのトークンは有効期限が2分なので、アクションの直前で取得する必要があります。そのため、HTML側で埋め込みという方法にはしていません。

流れは以下のようになっています。

  • 「登録」ボタンが押されたら、submitの通常動作を「preventDefault」で無効化
  • reCaptchaでトークンを取得
  • input要素を作成し、取得したトークンをセット
  • 作成したinputをform内に追加
  • submit発火

「grecaptcha」は後述のPHP側で読み込ませるreCaptchaのスクリプトで定義されています。

「frontData[‘sitekey’]」はwp_localize_scriptで送られてきたreCaptchaで取得したサイトキーになります。

「action」は好きなのを設定してください。PHP側で正しいリクエストだったかわかるようにしたいので、ログインなら「login」、コンタクトフォームなら「submit」など分けておくと良いです。

※nameのg-recaptcha-responseはv2の名残です。好きな名前でも機能させることはできます。調べるとほとんどのサイトがこの名前になっていると思いますので補足。

PHP側の設定

<?php
add_action( 'login_form_register', function() {
    if ( 'POST' === $_SERVER['REQUEST_METHOD'] ) {
        if ( ! get_option( 'users_can_register' ) ) {
            // 新規登録を許可しているか
        } elseif( ! isset( $_POST['register_login_nonce_field'] ) || ! wp_verify_nonce( $_POST['register_login_nonce_field'], 'register_login_nonce' ) ) {
            // ナンスチェック
        } elseif ( ! verify_recaptcha() ) {
            // reCaptchaを確認
        } else {
            // 登録処理

            wp_redirect( home_url( 'register-completed' ) );
            exit;
        }
 
        wp_redirect( home_url( 'register' ) );
        exit;
    }
} );

function verify_recaptcha() {
    if ( isset ( $_POST['g-recaptcha-response'] ) ) {
        $captcha_response = $_POST['g-recaptcha-response'];
    } else {
        return false;
    }

    $response = wp_remote_post(
        'https://www.google.com/recaptcha/api/siteverify',
        [
            'body' => [
                'secret'   => 'シークレットキー',
                'response' => $captcha_response
            ]
        ]
    );

    $success = false;
    if ( $response && is_array( $response ) ) {
        $decoded_response = json_decode( $response['body'] );
        if ( $decoded_response->success && $decoded_response->action === 'register' && $decoded_response->score > .5  ) {
            $success = true;
        }
    }

    return $success;
}

add_action( 'wp_enqueue_scripts', function() {
    // reCapchaを記述したファイル
    wp_enqueue_script( 'recaptcha-script', get_stylesheet_directory_uri() . '/assets/js/reCaptcha.js', [], false, false );
    wp_enqueue_script( 'recaptcha-api', 'https://www.google.com/recaptcha/api.js?render=' . 'サイトキー' , [], false, false );
    wp_localize_script( 'recaptcha-script', 'frontData', [
        'sitekey' => 'サイトキー'
    ] );
} );

ユーザーの登録時にフックしてreCpatchaのチェックを行います。

reCpatchaのチェックは以下の手順です。

  • 送信されてきたトークンの有無を確認
  • シークレットキーと共に「https://www.google.com/recaptcha/api/siteverify」へ送信
  • レスポンスが正常か確認
  • レスポンスが成功か確認
  • レスポンスのアクションが正しいか確認
  • レスポンスのスコアを判定

reCaptchaの確認用URLにシークレットキー、トークンを送信することで確認をすることができます。

返り値はreCapatchサイトで確認してください。

返り値を確認してOKか判断します。

レスポンスの「success」がOKかだけ判断するではなく、アクションも確かめることが公式からは推奨されています。(トークンが正しければOKが返ってきます。)

また、デフォルトのスコア判定は「> 0.5」のようです。(管理画面で確認できると書いてあるがどこかわかりませんでした。。。)

スコアは「0.0 ~ 1.0」の間です。0.5はデフォルトではじかれるということであれば「 >= 0.8」など絞り込むと良いかもしれません。

スクリプトでrecpacha apiにサイトキーを付与したものをつけるのを忘れないようにしましょう。

まとめ

以上でreCaptchaの実装が完了です。

サイトキーは管理画面の設定などに追加しておくと任意で変更ができるので便利です。

ローカル環境ではできないのかなと思いましたが、ローカル環境でも「localhost」などで追加してあげることで正常に確認することができます。