新「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リクエストする方法として参考にしたいと思う。

関連

お勧めコンテンツ

get_calendar(2009年12月10日 登録)

string get_calendar( [ bool $initial = true [, bool $echo = true ] ] )
投稿ページへのリンク付きカレンダー(1月分)を表示する。

is_day(2009年11月30日 登録)

bool is_day( )
要求されているページが、日別アーカイブページ(リクエストURLが/2009/11/30のように、書式が「/年/月/日」の場合)か調べる。

unregister_post_type(2016年5月23日 登録)

mixed unregister_post_type( string $post_type )
投稿タイプを未登録にする。

convert_smilies(2011年7月11日 登録)

string convert_smilies( string $text )
顔文字を対応する画像(imgタグ)に変換する。

get_post_format_slugs(2011年9月12日 登録)

string get_post_format_slugs( )
投稿フォーマットのスラッグ一覧を取得する。

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