ZATYのBLOG

お問い合わせする

WordPressログインURL変更プログラムのコード解説!

コード解説。WordPressのログインURLを変更するプログラム

前回WordPressのログインURLを変更するプログラムを紹介しました。

この記事では、「functions.phpにコピペするだけで変更することができる」という内容でしたので、プログラムの解説はしませんでした。

今回の記事はプログラムの解説をします。

ログイン変更プログラム

/**
 *  ログインURLを変更
 */
if (!class_exists('Login_Security')) :

  class Login_Security
  {
      const DEFAULT_LOGIN_NAME = 'wp-login.html';

      public function __construct()
      {
          $this->init();
      }

      private function init()
      {
          $this->hooks();
      }

      private function hooks()
      {
          add_action('template_redirect', array($this, 'login_redirect'));
          add_action('login_init', array($this, 'return_error_default_login_url'));
          add_filter('site_url', array($this, 'login_change_site_url'), 10, 2);
          add_filter('wp_redirect', array($this, 'login_wp_redirect'));
      }

      public static function return_error_default_login_url()
      {
          if (!defined('LOGIN_CHANGE') || sha1('page_changed') !== LOGIN_CHANGE) {
              global $wp_query;
              $wp_query->set_404();
              status_header(404);
              get_template_part(404);
              exit;
          }
      }

      public static function login_change_site_url($url, $path)
      {
          $require_login_name = apply_filters('login_endpoint_name', self::DEFAULT_LOGIN_NAME);
          if (strpos($path, 'wp-login.php') !== false
              && (is_user_logged_in()
                  || strpos($_SERVER['REQUEST_URI'], $require_login_name) !== false)) {
              $url = str_replace('wp-login.php', $require_login_name, $url);
          }
          return $url;
      }

      public static function login_wp_redirect($location)
      {
          $require_login_name = apply_filters('login_endpoint_name', self::DEFAULT_LOGIN_NAME);

          if (strpos($_SERVER['REQUEST_URI'], $require_login_name) !== false) {
              $location = str_replace('wp-login.php', $require_login_name, $location);
          }
          return $location;
      }

      public static function login_redirect()
      {
          $full_uri = (is_ssl() ? 'https' : 'http') . '://' . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
          $full_uri = explode('?', $full_uri)[0];

          $require_login_name = apply_filters('login_endpoint_name', self::DEFAULT_LOGIN_NAME);
          if ($full_uri === home_url('/') . $require_login_name) {
              header("HTTP/1.1 200 LOGIN PAGE");
              define('LOGIN_CHANGE', sha1('page_changed'));
              require_once(ABSPATH . '/wp-login.php');
              exit;
          }
      }
  }

  new Login_Security;

endif;

add_filter('login_endpoint_name', function() {
  return 'login';
});

/** / ログインURLの変更 */

プログラムの流れを確認

今回のプログラムはfunctions.php上でclassを使用しました。同一のフィルターフックを使用するので、可読性の目的でclassを利用することにしました。

このプログラムは

  • デフォルトのログインURLにアクセスされた時、404ページを表示する
  • WordPressデフォルトのログインページへのリンクを新ログインURLにする
  • 内部処理でwp-login.phpにリダイレクトするURLを新ログインURLに変更する
  • 新ログインURLにアクセスされた時、ログインページを表示する

という4つの関数を作成し、それぞれ適切なアクション・フィルターフックを指定します。

真ログインURLの文字列は、オリジナルのフィルターフックを作成し、後から変更することができるように設定しておきます。

それぞれのアクション・フィルターフックの解説

private function hooks()
{
  add_action('template_redirect', array($this, 'login_redirect'));
  add_action('login_init', array($this, 'return_error_default_login_url'));
  add_filter('site_url', array($this, 'login_change_site_url'), 10, 2);
  add_filter('wp_redirect', array($this, 'login_wp_redirect'));
}

4つのアクション・フィルターフックについて解説します。

なお、クラスのメソッドをコールバック関数に指定するので、第二引数が配列で指定する必要があるのが注意です。

template_redirectフック

add_action('template_redirect', array($this, 'login_redirect'));は真ログインURLにアクセスされた時にログインページを表示するためのアクションフックです。

template_redirectはwp_headより前に実行されるフックでドキュメントにまだ何も表示されていないので、PHPのheader関数を実行できます。

login_initフック

add_action('login_init', array($this, 'return_error_default_login_url'));はデフォルトのログインURLにアクセスされた際に404エラーになり、404ページを表示するためのアクションフックです。

login_initはログインページ(wp-login.php)にアクセスされた際に最初に実行されるフックです。

site_urlフック

add_filter('site_url', array($this, 'login_change_site_url'), 10, 2);はWordPressデフォルトのログインページへのリンクを新ログインURLにするためのフィルターフックです。

site_url関数はWordPressの独自関数で、サイトのドメインと第一引数に指定したパスを連結して出力します。

この関数は、WordPressのログアウトボタンやパスワードを忘れたときのリンク、ログインボタンなどで使用されています。例えばログアウトボタンであれば、以下のコードになり、出力されるURLは「https://example.com/wp-login.php?action=logout」になります。

site_url("wp-login.php?action=logout");

このフィルターフックは、コールバック関数の第一引数が返すURLになり、第二引数が与えたパスになります。なので、add_filter関数の第二引数を2以上に指定する必要があります。

wp_redirectフック

add_filter('wp_redirect', array($this, 'login_wp_redirect'));は内部処理でwp-login.phpにリダイレクトするときそのパスを新URLに変更するためのフィルターフックです。

具体的にはパスワードを忘れた際のページへのリダイレクトは「wp-login.php?action=lostpassword」と言うリダイレクト先のパスが指定されています。

このようにクエリが設定されることによりおこなれる処理があります。この処理が正しく通るようにフックを使用します。

コールバック関数のメソッドを解説

それではフックに使用したコールバック関数の部分のメソッドをそれぞれ解説します。

login_redirectメソッド

public static function login_redirect()
{
  $full_uri = (is_ssl() ? 'https' : 'http') . '://' . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
  $full_uri = explode('?', $full_uri)[0];

  $require_login_name = apply_filters('login_endpoint_name', self::DEFAULT_LOGIN_NAME);
  if ($full_uri === home_url('/') . $require_login_name) {
    header("HTTP/1.1 200 LOGIN PAGE");
    define('LOGIN_CHANGE', sha1('page_changed'));
    require_once(ABSPATH . '/wp-login.php');
    exit;
  }
}

このメソッドはGETパラメータ以外のURLに新URLの文字列が含まれているかを調べています。

$require_login_name = apply_filters('login_endpoint_name', self::DEFAULT_LOGIN_NAME);で新URLを変数に代入しています。フィルターフックを指定しているので、login_endpoint_nameにフックで指定することで、新URLを変更できる仕組みにしています。

define('LOGIN_CHANGE', sha1('page_changed'));ここでLOGIN_CHANGEと言う定数を用意しておくことで、このメソッドを通らずにログインページにアクセスできないようにしています。

最後にログインページのPHPファイルをインクルードすることでログインページを表示します。

return_error_default_login_urlメソッド

public static function return_error_default_login_url()
{
  if (!defined('LOGIN_CHANGE') || sha1('page_changed') !== LOGIN_CHANGE) {
    global $wp_query;
    $wp_query->set_404();
    status_header(404);
    get_template_part(404);
    exit;
  }
}

このメソッドは新URLを使用せずログインページにアクセスした場合に404エラーを返すメソッドです。

login_redirectメソッドで用意した「LOGIN_CHANGE」定数を持っていない場合404エラーになります。

デフォルトのwp-login.php直アクセスした際はこの定数が用意されていないので404エラーになるという仕組みになっています。

login_change_site_urlメソッド

public static function login_change_site_url($url, $path)
{
  $require_login_name = apply_filters('login_endpoint_name', self::DEFAULT_LOGIN_NAME);
  if (strpos($path, 'wp-login.php') !== false
    && (is_user_logged_in()
      || strpos($_SERVER['REQUEST_URI'], $require_login_name) !== false)) {
    $url = str_replace('wp-login.php', $require_login_name, $url);
  }
  return $url;
}

このメソッドは、site_url('wp-login.php')のように関数を使用された際に、wp-login.phpを新URLに変更するコードです。

site_urlのフィルターフックは第二引数にsite_urlの引数で指定した文字列(パス)が格納されています。

if文で、

「パスにwp-login.phpと言う文字列が含まれていていること」
「ユーザーがログインされているか、サイトのURLに新URLの文字列が含まれていること」

の同時を満たしているかを判断しています。この条件は、ログインページで使用されているsite_url('wp-login.php')と、ログイン状態の時のsite_url('wp-login.php')が対象になります。

この条件のとき、$urlに格納されている実際に返すURL文字列のwp-login.phpの文字列を新URLに置き換えています。

login_wp_redirectメソッド

public static function login_wp_redirect($location)
{
    $require_login_name = apply_filters('login_endpoint_name', self::DEFAULT_LOGIN_NAME);

    if (strpos($_SERVER['REQUEST_URI'], $require_login_name) !== false) {
        $location = str_replace('wp-login.php', $require_login_name, $location);
    }
    return $location;
}

このメソッドは、WordPressの内部リダイレクト処理が行なわれた際に、URLに新URL文字列が含まれていた場合にリダイレクト先をwp-login.phpではなく、新URL文字列に変更します。

具体的に作用する例は、パスワードを忘れた場合の処理が挙げられます。

ログイン画面から「パスワードをお忘れですか?」を押し、メールアドレスを入力し「新しいパスワードを取得」のボタンを押すと、"wp-login.php?checkemail=confirm"というページにリダイレクトされます。

このメソッドを追加していない場合、wp-login.phpは404エラーになるプログラムを使っているため、新しいパスワードを取得するメールが送信されなくなってしまいます。

まとめ

今回の記事は「コピペで簡単!WordPressのログインページを変更してセキュリティ対策」で紹介したプログラムの解説をしました。

新しいログインURLを作成する方法として、PHPファイルを用意しておく方法を紹介しているブログサイトも多いです。

この記事で紹介したプログラムでは、アクションフックやフィルターフックを駆使して、PHPファイルを用意することなく任意の文字列で、新ログインページの作成できるのが大きなメリットです。

ログインページを変更することは、セキュリティ対策としても有用です。しっかり理解した上で、セキュリティ対策をしていきましょう。

参考サイト

WordPress Developer Resources: リファレンス