REST API へのアクセスを制限するためのソースで躓いた話[WordPress]

WordPress

今回はWordPressのREST APIで躓いたので、今後同じようなことがないように備忘録として紹介させていただきます。

結果から言うと簡単に直すことが出来ましたが、原因を調査するのに時間がかかりました。。。

REST APIとは

REST APIとは、WordPress上のデータを外部から取得・更新できるAPIのことです。/

主な特徴は以下の通りです

  • WordPress 4.7から標準搭載されるようになった
  • 投稿、ページ、メディア、コメント、ユーザーなどのデータにアクセスできる
  • JavaScript経由でアクセスし、インタラクティブなWebサイトやアプリを作成できる
  • WP-CLIからコマンドラインでアクセスできる
  • 認証プラグインを使ってBasic認証やJWT認証を行う必要がある場合がある

WordPress REST APIを使うことで、管理画面を介さずにWordPressのデータを外部から取得・更新できるようになります。

これにより、WordPress以外の言語で開発したアプリケーションとWordPressを連携させたり、複数のWordPressサイト間でデータを共有したりするなど、WordPressの用途が大幅に広がります。
一方で、セキュリティ面での注意点もあります。REST APIエンドポイントをそのままにしておくと、データ盗難やフィッシングの危険性があるため、認証の設定などセキュリティ対策が必要です。

REST APIで制御していたときに出たエラー

REST APIで一部のプラグインの制御をしていた際に他プラグインでエラーが起こりました。

冒頭にも書きましたが結果から言うとすぐに解決したんですよね。
しかも1文追加するだけで。

そもそも何でエラーが出たってわかったの?

ある特定のプラグインが稼働しておらずグーグルクロームの「検証」で確認したら401のエラーメッセージが表示されていました。

調査方法は?

調査した方法は簡単で401メッセージをコピーし、function.phpを開き、先ほどコピーしたメッセージを貼り付けて該当のメッセージがないか検索していきます。
長文の場合で、かつ検索に引っかからなかったときは、冒頭以外を削除し検索。複数ある場合は文字を追加していき、、、を繰り返し該当箇所を見つけることが出来ました。

結果、以下のソースが発見されました。

function.phpに記入されていたREST API

function deny_rest_api_except_permitted($result, $wp_rest_server, $request) {

	$permitted_routes = ['contact-form-7'];

	$route = $request->get_route();

	foreach ($permitted_routes as $r) {
		if (strpos($route, "/$r/") === 0) return $result;
	}

		if (current_user_can('edit_posts') || current_user_can('edit_pages')) {
			return $result;
	}

	return new WP_Error('rest_disabled', __('The REST API on this site has been disabled.'), array('status' => rest_authorization_required_code()));
}
add_filter('rest_pre_dispatch', 'deny_rest_api_except_permitted', 10, 3);

私は設定した覚えがありませんので利用しているテーマの方で入っていたんでしょうか?
どやらこのソースが原因らしいです。

主な機能

  1. 許可されたルートのみ許可$permitted_routes 配列に指定されたルート(この例では “contact-form-7″)へのアクセスのみ許可されます。
  2. Gutenberg 編集権限ユーザーは許可: 投稿やページの編集権限を持つユーザーは、REST API へのアクセスが許可されます。
  3. それ以外は拒否: 上記の条件に当てはまらない場合は、REST API へのアクセスが拒否されます。

使用方法

  1. このコードをテーマの functions.php ファイルや、プラグインのメインファイルに追加します。
  2. $permitted_routes 配列に、許可したいルートを追加します。例えば、Contact Form 7 プラグインのルートを追加するなどします。
  3. Gutenberg 編集権限を持つユーザーを適切に設定します。

注意点

  • このコードは、REST API へのアクセスを制限するためのものです。必要に応じて、さらにセキュリティ対策を行う必要があります。
  • 許可するルートを適切に設定しないと、必要な機能が使えなくなる可能性があります。

解決方法は?

今回の解決方法ですがエラーを出しているプラグイン名を先程のソースに追加すればOKです。
例えばですが「Akismet」でエラーが出ている場合は下記ソースの用にプラグイン名を追加しましょう。

function deny_rest_api_except_permitted($result, $wp_rest_server, $request) {

	//Contact Form 7, Akismet 
	$permitted_routes = ['contact-form-7','akismet'];

	$route = $request->get_route();

	foreach ($permitted_routes as $r) {
		if (strpos($route, "/$r/") === 0) return $result;
	}

		if (current_user_can('edit_posts') || current_user_can('edit_pages')) {
			return $result;
	}

	return new WP_Error('rest_disabled', __('The REST API on this site has been disabled.'), array('status' => rest_authorization_required_code()));
}
add_filter('rest_pre_dispatch', 'deny_rest_api_except_permitted', 10, 3);

具体的にどこを変えたかというと下記となります。

	//Contact Form 7, Akismet 
	$permitted_routes = ['contact-form-7','akismet'];

‘contact-form-7’の後ろに,’akismet’と追加しています。「,」を忘れずに追加しましょう。

他のプラグインでエラーが出ている場合

他のプラグインでエラーが出ている場合は同様にプラグイン名を追加しいきましょう。
ただしこの場合のプラグイン名に関してですが、contact-form-7を例に上げると、単語と単語の間に「-(ハイフン)」が入っている場合があるので注意しましょう。

下記表は代表的なプラグイン名となっております。
下記の表にないプラグインの場合は、申し訳ないのですエラーが出ているプラグインのサポートページを御覧ください。

Yoast SEOyoast
WooCommercewoocommerce
Jetpack jetpack
Elementorelementor
WPFormswpforms
Akismetakismet
Contact Form 7contact-form-7
WP Rocketwp-rocket
Ninja Formsninja-forms
BuddyPressbuddypress
All in One SEO Packall-in-one-seo-pack
WP Super Cachewp-super-cache

まとめ

今回はREST API 制御で少し躓いたお話をさせていただきました。
本来であればREST APIを制御するソースなどはfunction.phpの方記載されていないかと思いますが、分け合って追加している方、もしくは私と同様に利用しているテーマの方で記載されている場合は、一度function.phpの方を検証してみてはいかがでしょうか?

追記

私の場合はfunction.phpにREST APIが記載されておりましたが、もしかしたらお使いのプラグインでREST APIの制御をしている場合もございます。
主にセキュリティ系のプラグインやキャッシュ系のプラグインが原因の場合もございます。
その時はお使いのセキュリティ(またはキャッシュ)系のプラグインを一度「無効化」することで解決する場合もございますのでお試しください。

セキュリティ(またはキャッシュ)系のプラグインが原因の場合は、REST APIを設定する項目がある場合もございますので、ご利用のプラグインのサポートページを御覧ください。

タイトルとURLをコピーしました