2026年5月20日

2026年5月20日

WordPress管理画面をBASIC認証で保護する方法(Apache・Nginx)

BASIC認証は、Webサーバー(Apache・Nginx)がページを返す前にユーザー名とパスワードを求める仕組みです。wp-login.php と /wp-admin/ にかけておくと、WordPressのログインフォームに届く前の段階で、認証情報を持たないアクセスを 401 で止められます。PHPが動く前に止まるので、ログイン画面への総当たり攻撃でサーバーの負荷が上がるのも抑えられます。

この記事では、Debian / Ubuntu の Apache 2.4 と Nginx を例に、設定と確認の手順を説明します(2026年11月時点。設定例は Apache 2.4.69 と Nginx の安定版で動作を確認しています)。

BASIC認証で守れるもの・守れないもの

設定の前に、効果の範囲を確認しておきます。

項目 BASIC認証での扱い
wp-login.php へのログイン試行 認証情報が無ければ 401 で止まる
/wp-admin/ 以下の管理画面 同上
xmlrpc.php(XML-RPC) 対象外。別途無効化や制限が必要
REST API(/wp-json/) 対象外
通信の暗号化 しない。認証情報はBase64で送られるだけなので HTTPS が前提

xmlrpc.php もユーザー名とパスワードを受け付ける入口なので、使っていなければ XML-RPCを無効化する手順 もあわせて行ってください。

また、会員登録したユーザーやショップの顧客が wp-login.php からログインするサイトでは、その人たちにもBASIC認証の情報を配る必要が出るため向きません。その場合は ログイン試行回数の制限 や IPアドレスによるログイン画面の制限 を検討してください。

手順1:パスワードファイル(htpasswd)を作る

パスワードファイルは htpasswd コマンドで作ります。ドキュメントルート(/var/www/html など)の外に置き、Webから読めないようにします。

# htpasswd コマンドを入れる
sudo apt install apache2-utils     # Debian / Ubuntu
# sudo dnf install httpd-tools     # RHEL / AlmaLinux / Rocky Linux

# 推測されにくいパスワードを作る(表示された文字列を控える)
openssl rand -base64 24

# 新しくファイルを作って1人目を登録(-c はファイルを作り直すので2回目以降は付けない)
sudo htpasswd -c -B /etc/apache2/.htpasswd-wp wp_guard

# 2人目を追加
sudo htpasswd -B /etc/apache2/.htpasswd-wp second_user

# 登録を削除
sudo htpasswd -D /etc/apache2/.htpasswd-wp second_user

# root が所有し、Webサーバーのグループだけ読めるようにする
sudo chown root:www-data /etc/apache2/.htpasswd-wp
sudo chmod 640 /etc/apache2/.htpasswd-wp
  • -B はパスワードを bcrypt で保存するオプションです。付けない場合は Apache 版の MD5(apr1)で保存されます。
  • www-data は Debian / Ubuntu で Apache と Nginx が動くユーザーです。RHEL系では Apache は apache、Nginx は nginx です。
  • Nginx で使うファイルは、Nginx の公式ドキュメントが対応形式として明記している apr1 で作れば読み込めます(-B を付けずに sudo htpasswd -c /etc/nginx/.htpasswd-wp wp_guard)。bcrypt が使えるかは OS の crypt() 関数の対応しだいです。

手順2:Apacheの設定(.htaccess)

.htaccess で認証を設定するには、そのディレクトリで AllowOverride AuthConfig(または All)が許可されている必要があります。WordPressのパーマリンクが動いていれば、多くの場合 All になっています。

wp-login.php にかける

WordPressのルート(wp-config.php がある場所)の .htaccess に、# BEGIN WordPress より上に追記します。# BEGIN WordPress から # END WordPress の間はWordPressが書き換えるので、そこには書きません。

# BASIC 認証: wp-login.php
<Files "wp-login.php">
    AuthType Basic
    AuthName "Restricted"
    AuthUserFile /etc/apache2/.htpasswd-wp
    Require valid-user
</Files>

/wp-admin/ にかける(admin-ajax.php は外す)

wp-admin ディレクトリの中に新しく .htaccess を作ります。

AuthType Basic
AuthName "Restricted"
AuthUserFile /etc/apache2/.htpasswd-wp
Require valid-user

# admin-ajax.php はサイトの表側からも呼ばれるので認証の対象から外す
<Files "admin-ajax.php">
    Require all granted
</Files>

admin-ajax.php は、ログインしていない訪問者のブラウザーからもプラグインやテーマが呼び出すファイルです。ここに認証をかけると、表側の検索・絞り込み・カート操作などが動かなくなることがあります。Apache 2.4 では、<Files> の中の Require がディレクトリ全体の Require valid-user より後に評価されて置き換わるため、このファイルだけ認証なしで通ります。

古い記事にある Satisfy Any と Allow from all は Apache 2.2 の書き方です。また <Directory> は .htaccess の中には書けません。サーバーの設定ファイル(バーチャルホスト)を編集できる場合は、上と同じ内容を <Directory "/var/www/html/wp-admin"> の中に書いても同じ効果になります。その場合は設定を確かめてから再読み込みします。

sudo apachectl configtest
sudo systemctl reload apache2

.htaccess の変更だけなら再読み込みは要りません。レンタルサーバーで使う場合、AuthUserFile にはサーバー上のフルパス(/ から始まるパス)を書きます。管理パネルにBASIC認証の設定機能があれば、そちらを使うほうが簡単です。

手順3:Nginxの設定

Nginx は .htaccess を読まないので、サイトの server { } ブロックに書きます。PHPの渡し先(fastcgi_pass)は環境に合わせてください(例: Ubuntu 24.04 の php8.3-fpm なら unix:/run/php/php8.3-fpm.sock)。

# server { } の中、既存の location ~ \.php$ と並べて書く

# BASIC 認証: wp-login.php
location = /wp-login.php {
    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd-wp;

    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}

# BASIC 認証: /wp-admin/ 以下
location ^~ /wp-admin/ {
    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd-wp;

    # admin-ajax.php は認証なしで通す
    location = /wp-admin/admin-ajax.php {
        auth_basic off;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }

    # /wp-admin/ 内の PHP を実行する(これが無いと PHP がそのまま返される)
    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
}

location ^~ /wp-admin/ は、一致すると正規表現の location(サーバー全体の location ~ \.php$)を調べなくなります。そのため、/wp-admin/ の中にもPHP用の location を入れ子で書く必要があります。これを忘れると、管理画面のPHPファイルが実行されずにソースのまま返されるおそれがあります。

sudo nginx -t && sudo systemctl reload nginx

Nginx の設定全体の作り方は NginxでWordPressを動かす設定 も参考にしてください。

手順4:動作を確かめる

コマンドラインから応答のステータスを確認します。-u にユーザー名だけを渡すと、パスワードは対話で聞かれるので履歴に残りません。

# 認証なし → 401 になればよい
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/wp-login.php
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/wp-admin/

# 認証あり → 200 になればよい
curl -s -o /dev/null -w "%{http_code}\n" -u wp_guard https://example.com/wp-login.php

# admin-ajax.php は 401 にならなければよい(action を付けない呼び出しは 400 が返る)
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/wp-admin/admin-ajax.php

最後にブラウザーで管理画面にログインし、表側のフォームや検索など admin-ajax.php を使う機能が動くことも確かめます。

運用上の注意

  • AuthName(auth_basic の文字列)はそろえる: ブラウザーは同じサイトの同じ領域名(realm)なら一度入力した認証情報を使い回すので、wp-login.php と /wp-admin/ で同じ名前にしておくと入力が1回で済みます。
  • admin-post.php: プラグインによっては、ログインしていない訪問者のフォーム送信先に /wp-admin/admin-post.php を使います(admin_post_nopriv_ フック)。表側のフォームが送信できなくなった場合は、admin-ajax.php と同じように除外します。
  • パスワードリセットと新規ユーザー: 再設定メールのリンク(wp-login.php?action=rp)もBASIC認証の対象になります。管理者以外がログインする場合は認証情報を伝えるか、管理者が WP-CLI の wp user update でパスワードを変更します。
  • ファイルの置き場所: .htpasswd-wp をドキュメントルートの中に置くと、設定しだいでWebから取得されるおそれがあります。外に置いてください。
  • ログイン画面の保護は他の対策と組み合わせる: BASIC認証のパスワードが漏れれば効果はなくなります。WordPress側の強いパスワードや二段階認証、総当たり攻撃への対策 も続けてください。

関連記事

お気軽にご相談ください

お見積りへ お問い合わせへ
▲