WordPress へログインする URL は決まっていますので、デフォルトのまま運用していますと攻撃される可能性が高いということで URL を変更する方法が取られます。プラグインを使うほどのこともないということで「プラグインなし」でググりますとたくさんヒットします。それらを見てみますとみなほぼ同じ方法をとっていますのでおそらく出所はどこか1ヶ所でありそのコピペと思われます。
で、その方法に疑問に感じる点がありましたので WordPress のログインプロセスを調べてみました。
01デフォルトでログインできる URL
ログインページを開く URL は https://ドメイン名/wp-login.php です。
ただこれだけではなく
- https://ドメイン名/wp-admin
- https://ドメイン名/login
- https://ドメイン名/admin
これらの URL でも https://ドメイン名/wp-login.php にリダイレクトされてログインページが表示されます。
ですので不正アクセスを防ぐには wp-login.php にアクセスできなくすればいいということになります。海外のサイトでは wp-login.php のファイル名を変えてしまうというかなり乱暴な方法がかなりヒットします。もちろん名前の変更だけではうまくいきませんので wp-login.php 内の ”wp-login.php” をすべて変えたファイル名に変更する必要があります。さらにこれだけではだめでログアウトやパスワードを忘れたときの URL にもフィルターフックをかけなくてはいけません。
この方法、試しにやってみたのですがやめたほうがいいです(笑)。
02ハッシュ化は必要ないと思うけど…
次に「wordpress ログインurl 変更 プラグインなし」でたくさんヒットする方法です。日本のサイトばかりで、おそらくどこか1ヶ所からのコピペと思われる方法です。
整理しますと方法は次のとおりです。
- WordPress サイトのルートに独自ログインファイル(仮に my_login.php)をつくり、
- 任意の定数(仮に MY_LOGIN)を定義する
- require_once で wp-login.php を読み込んでおく
- アクションフック login_init で my_login.php 以外をはねる
つまり、wp-login.php や wp-admin ではログインできなくなる - フィルターフック site_url で wp-login.php を my_login.php に書き換える
具体的にコードを示しますと、まず独自ログインファイルの my_login.php です。
<?php
//define('MY_LOGIN', password_hash('hogehoge', PASSWORD_DEFAULT));
//define('MY_LOGIN', sha1('hogehoge'));
define('MY_LOGIN', 'hogehoge');
require_once './wp-login.php';
ヒットするほとんどのサイトではコメントアウトした行のように password_hash や sha1 を使って定数をハッシュ化しています。
これが疑問なんですが、ハッシュ化する意味ってあるのでしょうか。というのは functions.php に書くアクションフック login_init を見てみますと、
if(!function_exists('login_redirect_home_url')){
function login_redirect_home_url(){
//if(!defined('MY_LOGIN') || !password_verify('hogehoge', MY_LOGIN)){
//if(!defined('MY_LOGIN') || sha1('hogehoge') !== MY_LOGIN){
if(!defined('MY_LOGIN') || 'hogehoge' !== MY_LOGIN){
wp_redirect(home_url());
exit;
}
}
}
add_action('login_init', 'login_redirect_home_url');
ハッシュ化する場合は上のコメントアウトしたコードになっています。これ、ハッシュ化しようがしまいが定数 MY_LOGIN は外から見えませんし、パスワード(上の hogehoge)は内部で使われているだけですのでハッシュ化せずにそのままの文字列で問題ないように思います。
コピペだと思われますので、ほとんどの記事でハッシュ化されていますがどうなんでしょう。私は意味がないと思いますが、なにか理由があるのかも知れません。
とにかく、最後のコード、フィルターフック site_url のコードは次のようになります。
if(!function_exists('login_replace_new_url')){
function login_replace_new_url($path, $scheme){
if(strpos($path, 'wp-login.php') && (is_user_logged_in() || strpos($_SERVER['REQUEST_URI'], 'my_login.php') !== false)){
$path = str_replace('wp-login.php', 'my_login.php', $path);
}
return $path;
}
}
add_filter('site_url', 'login_replace_new_url', 10, 2);
以上でログインURLの変更が可能になります。なお、コピペと思われる多くの記事にあるログアウト時のリダイレクトも必要ないと思います。
03functions.php 内で完了する方法
というハッシュ化の疑問があり、そもそも独自ログインファイルを作らなくてすむ方法はないだろうかということで、あれこれプラグインはどうやっているんだろうと調べていましたらいい方法が見つかりました。
functions.php 内にフックを3つ書けば OK です。
もう一度確認しますと、ログインURL変更するためには次の3点をクリアすればいけるということです。
- アクションフック login_init でデフォルトのログインをはねる
- 独自ログインURLであれば wp-login.php に送る
- ログイン中に呼ばれる wp-login.php を独自ログインURLのパスに差し替える
1 と 3 は上の項目と同じで問題ありません。
残る 2 ですが、上の項目の方法では独自ログインファイル内で wp-login.php を読み込んでいます。それを functions.php に書き込んでも有効となるアクションフックで読み込む方法です。
次のコードを functions.php に書き込めばログインURLを https://ドメイン名/hogehoge に変更することができます。hogehoge は変更してください。
// wp-login.php に変わるパスを定数 IMZ_SECURITY_LOGIN に入れる
define ('IMZ_SECURITY_LOGIN', 'hogehoge');
// wp-login.php, wp-admin などデフォルトログインをはねる
function imz_redirect_invalid_login() {
if (strpos($_SERVER['REQUEST_URI'], IMZ_SECURITY_LOGIN) === false) {
wp_redirect(home_url());
exit;
}
}
add_action('login_init', 'imz_redirect_invalid_login');
// 独自ログインURLであれば wp-login.php に送る
function imz_new_login_page() {
$request = $_SERVER['REQUEST_URI'];
$login = '/' . IMZ_SECURITY_LOGIN;
if ($request == $login || strpos( $request, $login . '?') === 0 ) {
global $user_login, $error;
$user_login = '';
$error = '';
require_once(ABSPATH . 'wp-login.php');
exit;
}
}
add_action('after_setup_theme', 'imz_new_login_page');
// ログイン中に呼ばれる wp-login.php を独自ログインURLのパスに差し替える
function imz_change_login_url($url, $path) {
if (($path === 'wp-login.php' || preg_match('/wp-login\.php\?action=\w+/', $path)) && (is_user_logged_in() || strpos($_SERVER['REQUEST_URI'], IMZ_SECURITY_LOGIN) !== false)) {
$url = str_replace('wp-login.php', IMZ_SECURITY_LOGIN, $url);
}
return $url;
}
add_filter('site_url', 'imz_change_login_url', 10, 2);
2つ目のアクションフック ‘after_setup_theme’ は ’init’ でも問題ありません。functions.php が読み込まれた後の最初のアクションフック after_setup_theme を使っているだけでその次の init でも同じです。
私はプラグインを使わずにオリジナルのテーマですべて完了することを目指していますのでまたひとつクリアできたということです。