1. WordPress

【WordPress】wp_nonce_field() と check_admin_referer() でフォームのセキュリティ対策を行う方法

Share

WordPressで管理画面や独自のフォームを作成する際、CSRF(クロスサイトリクエストフォージェリ)攻撃からフォームを守るためには、Nonce(ナンス)という仕組みを利用することが推奨されています。

この記事では、wp_nonce_field()check_admin_referer() を使ったセキュリティ対策の方法をわかりやすく解説します。

Nonceとは?

Nonce(ナンス)は、「一度だけ使える使い捨てのトークン」のようなものです。これにより、意図しない第三者からの不正リクエスト(たとえばフォームのなりすまし送信)をブロックできます。

WordPressでは wp_nonce_field() でNonceをフォームに出力し、check_admin_referer() で送信時に確認を行うことで安全な処理が実現できます。

wp_nonce_field() の使い方

wp_nonce_field() は、フォーム内にNonce用の<input type="hidden">を自動出力する関数です。

基本構文

wp_nonce_field( $action, $name, $referer, $echo );
  • $action(必須):Nonceを作成する際の一意な識別子。
  • $name(任意):hiddenフィールドの name 属性(デフォルトは _wpnonce)。
  • $referer(任意):リファラチェック用の hidden フィールドを出力するか(デフォルトは true)。
  • $echo(任意):直接出力するか、戻り値として返すか(デフォルトは true)。

<form method="post">
    <?php wp_nonce_field( 'my_form_action', 'my_nonce_field' ); ?>
    <input type="text" name="example" />
    <input type="submit" value="送信" />
</form>

このコードにより、name="my_nonce_field" の hidden フィールドが追加されます。

check_admin_referer() の使い方

フォーム送信時に check_admin_referer() を使うことで、Nonceの整合性とリファラを検証できます。

基本構文

check_admin_referer( $action, $query_arg );
  • $actionwp_nonce_field() で指定した $action と一致させる必要があります。
  • $query_arg$_POST または $_GET に含まれるNonceのキー(省略可。デフォルトは _wpnonce)。

if ( isset( $_POST['example'] ) ) {
    check_admin_referer( 'my_form_action', 'my_nonce_field' );
    // 検証成功時の処理
    echo 'セキュリティチェック成功!';
}

Nonceが不正だった場合は、「403 Forbidden」エラーが表示され、処理は強制停止します。

実践:簡単なセキュリティ対応付きフォーム

<?php
if ( isset( $_POST['example_text'] ) ) {
    check_admin_referer( 'secure_form_action', 'secure_nonce' );
    // 入力値の処理
    echo 'データを安全に受け取りました。';
}
?>

<form method="post">
    <label for="example">入力:</label>
    <input type="text" name="example_text" id="example">
    <?php wp_nonce_field( 'secure_form_action', 'secure_nonce' ); ?>
    <input type="submit" value="送信">
</form>

カスタムフィールドの表示・保存をセキュアに実装する方法

wp_nonce_field()check_admin_referer() は、カスタムフィールドの保存処理にも活用されます。以下は、投稿編集画面にオリジナルのカスタムフィールドを追加し、セキュリティチェック付きで保存するコード例です。

カスタムフィールドのメタボックスを表示

<?php
function my_custom_field_meta_box() {
    add_meta_box(
        'my_custom_field_id',
        'カスタムフィールド',
        'my_custom_field_callback',
        'post',
        'normal',
        'high'
    );
}
add_action( 'add_meta_boxes', 'my_custom_field_meta_box' );

function my_custom_field_callback( $post ) {
    $value = get_post_meta( $post->ID, '_my_custom_field', true );
    wp_nonce_field( 'my_custom_field_action', 'my_custom_field_nonce' );
    ?>
    <label for="my_custom_field_input">カスタム入力:</label>
    <input type="text" id="my_custom_field_input" name="my_custom_field_input" value="<?php echo esc_attr( $value ); ?>" />
    <?php
}

カスタムフィールドの保存処理

function my_save_custom_field( $post_id ) {
    // 自動保存のときは何もしない
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
        return;
    }

    // 権限チェック
    if ( ! current_user_can( 'edit_post', $post_id ) ) {
        return;
    }

    // Nonce チェック
    if ( ! isset( $_POST['my_custom_field_nonce'] ) || 
         ! check_admin_referer( 'my_custom_field_action', 'my_custom_field_nonce' ) ) {
        return;
    }

    if ( isset( $_POST['my_custom_field_input'] ) ) {
        $sanitized = sanitize_text_field( $_POST['my_custom_field_input'] );
        update_post_meta( $post_id, '_my_custom_field', $sanitized );
    }
}
add_action( 'save_post', 'my_save_custom_field' );

説明

  • add_meta_box():投稿編集画面にメタボックス(入力エリア)を追加します。
  • wp_nonce_field():入力エリアにセキュリティトークンを出力します。
  • check_admin_referer():保存処理のときにNonceが正しいか検証します。
  • sanitize_text_field():ユーザー入力をサニタイズ(無害化)してから保存します。

このように、Nonceを使うことで、外部からの不正なPOSTリクエストによる情報の書き換えを防ぎ、安全にカスタムフィールドの保存処理を実装できます。

よくある注意点

  • check_admin_referer() は失敗時に 自動的にスクリプトを停止するため、if 文などで条件を分ける必要はありません。
  • Nonceは時間制限付き(デフォルト24時間)なので、古いページを開きっぱなしにして送信するとエラーになる場合があります。
  • 管理画面外(フロントエンドなど)で使う場合は、check_ajax_referer() を使うこともあります。

参考リンク