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 );
$action
:wp_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()
を使うこともあります。