タグアーカイブ Easy Digital Downloads

EDDのログインフォームにロックアウト時のカスタムエラーメッセージを表示する方法

Easy Digital Downloads(以下、EDD)のログインフォームでセキュリティプラグインのロックアウト時にカスタムエラーメッセージが表示されない原因は、EDDがwp-login.phpの login_errors フィルターを通らない独自のエラー処理を持つことにある。authenticate フィルターに優先度30のフックを追加し、ロックアウトエラーをEDDのエラー表示システムへ渡せば解決する。

なぜEDDのログインフォームではカスタムエラーメッセージが表示されないのか

なぜEDDのログインフォームではカスタムエラーメッセージが表示されないのか

WordPress標準のログインページ(wp-login.php)は、ログイン時に発生したエラーを login_errors フィルターを通して画面へ表示する。セキュリティプラグインの多くはこのフィルターにフックし、ロックアウト時に「ログイン試行回数の上限に達しました」などのカスタムメッセージへ置き換えている。

一方、EDDのチェックアウト画面や [edd_login] ショートコードが生成するログインフォームは、認証処理を自前で実行する。内部では wp_signon() を呼び出すものの、返ってきたWP_Errorをそのまま表示せず、エラーコードごとに独自のメッセージへ変換してしまう。ロックアウト系のエラーコードはこの変換テーブルに存在しないため、標準メッセージ「ユーザー名またはパスワードが間違っています」に置き換えられてしまう。

つまり、セキュリティプラグインは正常にロックアウトを検知してカスタムメッセージ付きのWP_Errorを返しているにもかかわらず、EDDのエラー処理がそれを捨てて汎用メッセージに差し替えているのが根本原因だ。

Before(修正前)
ユーザー名またはパスワードが間違っています
ロックアウトされていても標準メッセージだけが表示される
↓
After(修正後)
ログイン試行回数の上限に達しました。15分後に再度お試しください
ロックアウト状態と待機時間が顧客に伝わる
■ 修正前 ■ 修正後

このデモは、ロックアウト時の表示が標準メッセージからカスタムメッセージへ変わる流れを示したイメージだ。

authenticateフィルターでEDDにエラーを渡す手順

authenticateフィルターでEDDにエラーを渡す手順

解決のアプローチは、EDDがエラーを独自メッセージへ変換する前に、ロックアウトのWP_Errorを検知してEDDのエラーシステムへ正しいメッセージを登録することだ。WordPressの authenticate フィルターは認証処理の中で必ず実行されるため、プラグイン本体を変更せずにフックを追加できる。

STEP 1 セキュリティプラグインがロックアウトを検知してWP_Errorを返す
↓
STEP 2 追加フックがauthenticateフィルターでWP_Errorを捕捉する
↓
STEP 3 エラーコードを判定してロックアウトかどうかを確認する
↓
STEP 4 EDDのエラー表示にカスタムメッセージを渡す

このデモは、認証時のエラーがEDDのログインフォームまで正しく届く流れを示している。

authenticateフィルターに追加する実装コード

authenticateフィルターに追加する実装コード

以下のコードを子テーマのfunctions.phpまたはカスタムプラグインへ追加する。authenticate フィルターの優先度は30に設定し、セキュリティプラグインが通常使う優先度20より後に実行されるようにする。これにより、ロックアウトのWP_Errorが返った段階で確実に捕捉できる。

/**
 * EDD のログインフォームでロックアウト時のカスタムエラーメッセージを表示する
 */
function custom_edd_show_lockout_error( $user, $username, $password ) {
    if ( is_wp_error( $user ) ) {
        $error_code = $user->get_error_code();

        // ロックアウト系のエラーコードを判定するパターン
        $lockout_patterns = array(
            'lockout',
            'too_many',
            'attempts',
            'blocked',
            'limit',
            'tries',
        );

        $is_lockout = false;
        foreach ( $lockout_patterns as $pattern ) {
            if ( strpos( strtolower( $error_code ), $pattern ) !== false ) {
                $is_lockout = true;
                break;
            }
        }

        // ロックアウトエラーなら EDD のエラーシステムへ登録する
        if ( $is_lockout && function_exists( 'edd_set_error' ) ) {
            edd_set_error( 'login_lockout', $user->get_error_message() );
        }
    }

    return $user;
}
add_filter( 'authenticate', 'custom_edd_show_lockout_error', 30, 3 );

コード内の $lockout_patterns 配列は、セキュリティプラグインが返すエラーコードに合わせて調整する。エラーコードはプラグインごとに異なるため、実際の環境で確認しながらパターンを追加するとよい。

エラーコードを確認してパターンを調整する方法

エラーコードを確認してパターンを調整する方法

セキュリティプラグインが返すエラーコードは、デバッグログやテストコードで確認できる。たとえば、一時的に以下のコードを追加してロックアウトを再現し、error_log() に出力すれば正確なエラーコードを把握できる。

// 一時的なデバッグ用コード(確認後に削除する)
function debug_edd_login_error( $user, $username, $password ) {
    if ( is_wp_error( $user ) ) {
        error_log( 'EDD login error code: ' . $user->get_error_code() );
        error_log( 'EDD login error message: ' . $user->get_error_message() );
    }
    return $user;
}
add_filter( 'authenticate', 'debug_edd_login_error', 25, 3 );

ロックアウトを発生させた後、サーバーのエラーログ(debug.log)を確認すると、セキュリティプラグインが返したエラーコードが記録されている。このコードを前セクションの $lockout_patterns に追加すれば、確実に判定できる。

functions.phpへコードを追加する前の確認事項

コードを本番サイトへ追加する前に、いくつか確認しておくべき点がある。まず、子テーマを使用しているか確認する。親テーマのfunctions.phpを直接編集すると、テーマのアップデートでコードが消えるため、必ず子テーマのfunctions.phpまたはカスタムプラグインへ追加する。

次に、ロックアウトを再現できるテスト環境を用意する。自分の管理画面からのログイン試行でテストすると、自分自身がロックアウトされて管理画面へアクセスできなくなる可能性がある。ブラウザのプライベートウィンドウや別の端末からテストするのが安全だ。

さらに、edd_set_error() 関数はEDDが有効化されている場合にのみ存在する。コード内で function_exists() による存在確認を入れているため、EDDが無効化されてもエラーは発生しないが、EDD以外のログインフォームではこの方法は機能しない点に注意する。

よくある質問

このコードはWooCommerceのログインフォームでも使えますか?

基本的な考え方は同じだが、edd_set_error() はEDD専用の関数だ。WooCommerceの場合は wc_add_notice() を使うか、WooCommerceのログインフォーム用フィルターを利用する必要がある。フックするポイントは authenticate フィルターで共通だが、エラーを登録する関数を各プラグインのものへ置き換える。

セキュリティプラグインの種類によってエラーコードは異なりますか?

異なる。プラグインごとに独自のエラーコードを割り当てているため、「too_many_retries」「lockout」「attempts_exceeded」など名称はさまざまだ。デバッグコードで実際のエラーコードを確認し、パターン配列を調整するのが確実だ。

EDDのバージョンアップでコードが動作しなくなることはありますか?

可能性はある。EDDの内部実装やエラー処理の方法が変更された場合、edd_set_error() の動作も変わる可能性がある。メジャーアップデート後はロックアウト時の表示を必ずテストし、問題があればエラーコードの確認からやり直すとよい。

コードを追加して問題が起きた場合の復旧方法は?

FTPまたはサーバーのファイルマネージャでfunctions.phpを開き、追加したコードを削除すれば元に戻る。FTPが使えない場合は、サーバー会社の管理画面からファイル編集機能を利用するか、バックアップから復元する。コード追加前に必ずバックアップを取っておくこと。

この方法でwp-login.php側のカスタムメッセージも変更されますか?

変更されない。authenticate フィルターで edd_set_error() を呼び出しても、wp-login.phpの表示には影響しない。wp-login.phpは引き続き login_errors フィルターを通してメッセージを表示するため、両方のログインフォームでカスタムメッセージを表示したい場合は、セキュリティプラグイン本来の設定とこの追加コードが共存する。

この記事のポイント

  • EDDのログインフォームはwp-login.phpの login_errors フィルターを通らない
  • authenticate フィルターに優先度30のフックを追加してロックアウトエラーを捕捉する
  • edd_set_error() へカスタムメッセージを登録すればEDDのログインフォームに表示される
  • エラーコードのパターンはセキュリティプラグインごとに調整が必要
  • 子テーマのfunctions.phpへ追加し、テスト環境で動作確認してから本番へ適用する