WordPressのサイトからいろいろな情報を取得できるREST API。例えば投稿の情報を取得したければ以下のようなURLにアクセスすると簡単に情報が引き出せます。
サイトのURL/wp-json/wp/v2/posts
また以下のようにパラメーターを付けると、必要な件数の情報も取得できます(コードは10件)。
サイトのURL/wp-json/wp/v2/posts?per_page=10
まあ、自身で運営しているサイトの情報を取得して表示させたいといった場合には便利なものではあるのですが、以下のURLで特定のユーザーの情報なども取得できてしまいます(ユーザーIDが1の人の情報)。
サイトのURL/wp-json/wp/v2/users/1
どちらも日本語の文字がUnicodeになっているので、ぱっと見は何が書いてあるのかが分かりませんが、Unicodeエスケープシーケンス変換ツールなどを使えば簡単に分かってしまいます。
試しに自身のサイトのURLを使って、どんな風に情報が出力されるのか確認してみてください。
WordPressの標準仕様では、この情報は誰でも取得できてしまうので、悪意を持って使えば、投稿情報に関しては他人のサイトの情報を集めて、いわゆるキュレーションなどというようなサイトが簡単に作れてしまいますし、ユーザー情報であれば、ユーザー名が丸わかりになってしまう(つまりあとはパスワードが分かればサイトの乗っ取りが可能になってしまう)のです。
本当にこれは、WordPress側としても、あくまでも自己所有のサイト同士を簡単につなげられるようにという意図で解放されているのですが、いつの間にかサイトの投稿情報が抜かれていたり、ユーザー名がバレちゃったりしてると思うと、ちょっと怖いですね...。
そこで本ページでは、このREST APIを無効にする方法と、条件に応じて解放する方法を紹介します。
設定後はアクセス制限がきちんとできているかを必ず確認してください
本ページ掲載のコードを使用するときは
本ページで掲載しているコードは、以下に了承した上で使用ください
- コードは商用・非商用問わず自由に使っていただいて構いませんが、コード追加による不具合やトラブルが発生しても当方では一切責任を負いません
- コードは有効化しているテーマのfunctions.php、style.cssなどへ追加することで機能します。それらのファイルへの変更を行うことに不安のある方は使用しないでください
- コードは本ページの公開日時点で私の環境において動作したものです。WordPressバージョン他環境の違いによって動作しないことがあります
- コードは、セキュリティ、コードの正確さなどにおいて完全なものではありません。中には紹介するコードを簡略化するために省略している部分があるものもありますので、ご自身でコードを十分に検証し、必要な部分の編集を行った上で使用するようにしてください
- 掲載しているのは参考コードです。自身の環境に合わせるための編集はご自身で対応いただく必要があります(コメント欄等から質問いただいても基本回答は致しません)
- 掲載しているコードの転載を禁じます(SNSで紹介いただいたり、本ページへのリンクを張っていただくことは大歓迎です)
REST APIのアクセス制限を行うコード
基本コード
REST APIへのアクセス(いわゆる叩くという行為)を制限するには、以下の基本コードを作り、そこに条件を追加していきます。
/***** Rest apiの使用を無効にする *****/
function pwcn_deny_restapi_except_plugins( $result, $wp_rest_server, $request ){
$namespaces = $request->get_route();
/** ここから下に除外する条件を指定する **/
/** ここから上に除外する条件を指定する **/
//除外条件に合致しない(拒否する)場合のメッセージ
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', 'pwcn_deny_restapi_except_plugins', 10, 3 );
このコードをまず追加して、先ほどのREST APIアクセス用のURLへアクセスしてみましょう。
こんな感じで拒否され、素っ気ない画面が出るはずです。

こうならない場合にはこの後の措置をしてもコードが有効になりませんのでよく確認してください。
続いて除外条件を「/** ここから下に除外する条件を指定する **/」~「/** ここから上に除外する条件を指定する **/」の間に追加していきます。
ケースによる除外条件の追加
ブロックエディターを除外する
実はWordPressではブロックエディターでもREST APIを使っていろいろな情報を取得していて、除外しないと基本的にブロックエディターが使えませんから、以下のコードを追加して除外します。
//寄稿者権限以上の場合はオフ(ブロックエディタは除外する)
if ( current_user_can( 'edit_posts' ) ) {
return $result;
}
埋め込みを除外する
WordPressには段落ブロックの先頭にURLを入れると、カード化できるものはカード表示するようになっています。この機能が必要な場合には、以下を追加して除外します。
//oembedの除外
if( strpos( $namespaces, 'oembed/' ) === 1 ){
return $result;
}
Jetpackプラグインの除外
Jetpackプラグインではいろいろな情報の提供や取得にREST APIを利用していますので、このプラグインを使用している場合には以下のコードで除外します。
//Jetpackの除外
if( strpos( $namespaces, 'jetpack/' ) === 1 ){
return $result;
}
Contact Form7プラグインの除外
Contact Form7プラグインでもREST APIを使用していますので、このプラグインを使用しているサイトでは以下のコードを追加して除外します。
//Contact Form7の除外
if( strpos( $namespaces, 'contact-form-7/' ) === 1 ){
return $result;
}
Redirectionプラグインの除外
ページのリダイレクトを行う「Redirection」プラグインを使用している場合は以下のコードで除外します。
//Redirectionの除外
if( strpos( $namespaces, 'redirection/' ) === 1 ){
return $result;
}
Download Managerプラグインの除外
ファイルのダウンロード提供を管理する「Download Manager」プラグインを使用している場合は以下のコードで除外します(除外しないとレポートの一部が正常に表示されません)
//Download Manager(レポートの一部エンドポイント)の除外
if( strpos( $namespaces, 'wp/v2/dlm_download' ) === 1 ){
return $result;
}
同一のグローバルIPを持つサーバーからのアクセスを除外
複数のWordPressを階層化していたり、同じ契約のサーバー上に別のドメインを持つ複数のサイトがある場合で、相互に許可したい場合には以下のコードで除外します。
// 同一ホストからのアクセスを許可
$server_ip = $_SERVER['SERVER_ADDR']; // サーバーのIPアドレス
$client_ip = $_SERVER['REMOTE_ADDR'];
if ( $client_ip === $server_ip ) {
return $result;
}
特定のグローバルIPアドレスを持つサーバーからのアクセスを除外
別のサーバーや契約で管理していてグローバルIPは別だけどアクセスを許可したい場合には、以下のコードを追加します。
$allowed_ipsに許可するIPアドレスを指定すれば(コード例では「111.111.111.111」と「222.222.222.222」を許可)そのグローバルIPアドレスからの要求のみ許可されます
//特定のグローバルIPを持つサーバーからのアクセスを許可
$allowed_ips = array( '111.111.111.111', '222.222.222.222' ); // 許可するIPアドレスのリスト
$client_ip = $_SERVER['REMOTE_ADDR'];
if ( in_array( $client_ip, $allowed_ips ) ) {
return $result; // 許可されたIPアドレスからのアクセスは許可
}
コメントを残す