新「WordPress Events and News」ウィジェットが興味深い

(4.8.0以降)
新「WordPress Events and News」ウィジェットが興味深い - nonce消失?事件

説明

4.8のベータ版ですぐに新機能とわかるのが管理者ダッシュボードの新「WordPress Events and News」ウィジェット。ユーザーが指定した地域近隣で開催されるイベント情報を表示してくれるウィジェットで、この中のフォームがちょっと興味深かった。なおこの記事はWordPress 4.8 beta-2をもとにしており、以降のバージョンで変更される可能性があることをあらかじめ断っておく。

地域を指定するフォームにnonceがない
「WordPress Events and News」ウィジェット

「WordPress Events and News」ウィジェットの「地域登録フォーム」は通常は非表示になっており、「鉛筆」アイコンをクリックすることで表示と非表示を切り替えできる。この地域登録フォームのHTMLは次のようになっている(便宜上、空白文字を除外)。

<form class="community-events-form" aria-hidden="false" action="http://localhost/wp-admin/admin-ajax.php" method="post">
<label for="community-events-location">City:</label>
<input id="community-events-location" class="regular-text" type="text" name="community-events-location" placeholder="Cincinnati">
<input type="submit" name="community-events-submit" id="community-events-submit" class="button" value="送信">
<button class="community-events-cancel button-link" type="button" aria-expanded="true">キャンセル</button>
<span class="spinner"></span>
</form>

とてもシンプルな内容だが、「クイックドラフト」ウィジェットなどにある「クロスサイトリクエストフォージェリ(CSRF)」対策でおなじみの「nonce」設定が見当たらない。「nonce」設定をどこで行っているのか気になったので、リクエストの流れを追ってみた。

AJAXのリクエストハンドラを探す

4.8で追加されたAJAX関連を見ていくと、/wp-admin/includes/ajax-actions.phpにwp_ajax_get_community_events関数が追加されている。この関数の冒頭部分では次のようにcheck_ajax_referer関数が呼び出されており、nonce値のチェックは行われていることがわかる。

check_ajax_referer( 'community_events' );

ここでチェックしているnonce値は動的に生成するものなので、「WordPress Events and News」ウィジェットのあるページに出力されていると予想して出力されたHTMLソースを見てみると、フッター部分のJavaScriptに次のような記述が見つかりました(そのままだと見難いので整形)。

var communityEventsData = {
	"nonce":"67f3177442",
	"cache":"",
	"l10n":{
		"enter_closest_city":"Enter your closest city to find nearby events.",
		"error_occurred_please_try_again":"An error occurred. Please try again.",
		"attend_event_near_generic":"Attend an upcoming event near you.",
		"could_not_locate_city":"We couldn&#8217;t locate %s. Please try another nearby city. For example: Kansas City; Springfield; Portland.",
		"city_updated":"City updated. Listing events near %s."
		}
	};

この変数の定義がどこで出力されているかというと、'admin_print_scripts-index.php'アクションとして実行されるwp_localize_community_events関数でwp_localize_script関数を使っていました。communityEventsData変数のconce値は、「地域登録フォーム」で「送信」ボタンが押された場合に動作する/wp-admin/js/dashboard.jsのgetEventsメソッドにおいてAJAXリクエスト時に使用されている。

requestParams          = requestParams || {};
requestParams._wpnonce = communityEventsData.nonce;
requestParams.timezone = window.Intl ? window.Intl.DateTimeFormat().resolvedOptions().timeZone : '';

initiatedBy = requestParams.location ? 'user' : 'app';

$spinner.addClass( 'is-active' );

wp.ajax.post( 'get-community-events', requestParams )

wp.ajax.postメソッドの第1パラメータで指定している'get-community-events'がWordPressのAJAXリクエストのactionパラメータ、第2パラメータが実際に送信されるパラメータ(この場合は$_POSTに格納される内容)のようだ。

これからのAJAXリクエストフォーム

JavaScriptのプログラム要素はファイルに記載し、リクエスト時の状況に応じて変動するデータをwp_localize_script関数で動的に出力するこの方法は個人的には好ましい。プラグイン開発においてフォームからAJAXリクエストする方法として参考にしたいと思う。

関連

お勧めコンテンツ

the_custom_logo(2016年5月22日 登録)

void the_custom_logo( [ int $blog_id = 0 ] )
カスタムロゴを表示する。

wp_next_scheduled(2014年5月26日 登録)

mixed wp_next_scheduled( string $hook [ , array $args = array() ] )
スケジュールに登録されているアクションの実行時間を取得する。

wp_cache_set(2011年8月26日 登録)

bool wp_cache_set( mixed $id, mixed $data [, string $flag = '' [, int $expire = 0 ] ] )
任意のデータをキャッシュに保存する。

add_filter(2010年5月18日 登録)

bool add_filter( string $tag, mixed $function_to_add [ , int $priority = 10 [ , int $accepted_args = 1 ] ] )
WordPressシステムの関数にフィルター関数を追加する。

wp_make_link_relative(2014年12月19日 登録)

mixed wp_make_link_relative( mixed $link )
URLからフルパス名を取得する。

最終更新日時 : 2017-05-26 14:43