2026年9月16日

2026年9月16日

WordPressのパスワード強度ルールをカスタマイズする方法

WordPress標準のパスワード強度メーターは「弱い」と表示するだけで、弱いパスワードの保存自体は止めません。独自の強度ルールを実際に効かせるには、プロフィール更新とパスワードリセットのサーバー側処理で検証を加える必要があります。この記事では、標準の仕組みを確認したうえで、どんなルールにすべきか、mu-pluginでの実装方法、プラグインを使う場合の選択肢までを説明します。

標準のパスワード強度チェックの仕組み

WordPressのプロフィール画面やパスワードリセット画面には、入力中のパスワードを評価するメーターがあります。これはブラウザ上で動くJavaScript(zxcvbnという評価ライブラリ)による判定で、よくある単語や並び、ユーザー名との類似を見て「非常に弱い」から「強力」までを表示します。

弱いパスワードを入力すると「脆弱なパスワードの使用を確認」といった趣旨のチェックボックスが表示され、そこにチェックを入れれば保存できてしまいます。しかも判定はブラウザ側なので、JavaScriptを介さない送信には効きません。つまり標準の仕組みは「注意を促す」機能であり、ルールを強制したいならサーバー側での検証が必須です。

どんなルールにするか

「大文字・小文字・数字・記号を各1文字以上」のような文字種の組み合わせを強制するルールは、Password1! のような予測しやすいパスワードを生みがちです。米国NISTのデジタル認証ガイドライン(SP 800-63B)も、文字種の強制や定期的な変更の強制より、長さを重視し、漏えい済みやよく使われるパスワードを拒否する方向を示しています(2026年10月現在)。最新の推奨値は改訂で変わるため、採用前に原文を確認してください。

実務的には次のルールが扱いやすく、効果も高めです。

  • 最低文字数:12文字以上など、十分な長さを求める
  • よく使われるパスワードの拒否:password、12345678、サイト名などを拒否する
  • ユーザー名・メールアドレスを含むものの拒否:推測の手がかりになるため
  • 上限は緩く:長いパスフレーズを妨げないよう、極端に短い上限を設けない

パスワードの強さだけで守れる範囲には限界があるため、管理者アカウントには二要素認証、ログイン画面には試行回数の制限を併用するのが前提です。

mu-pluginでサーバー側の検証を追加する

検証が必要なのは主に次の2か所です。

  • プロフィール画面と管理画面からのユーザー追加・編集:user_profile_update_errors アクション
  • wp-login.phpのパスワードリセット画面:validate_password_reset アクション

どちらも WP_Error オブジェクトにエラーを追加すると保存が中止され、画面にメッセージが表示されます。作業前にバックアップを取り、ステージング環境で動作を確認してから本番に置いてください。

<?php
/**
 * Plugin Name: Password Policy (Server-side)
 * 置き場所: wp-content/mu-plugins/password-policy.php
 */
defined( 'ABSPATH' ) || exit;

/**
 * パスワードがルールに合わない理由を配列で返す。合っていれば空配列。
 * パスワードは比較にだけ使い、保存・ログ出力・画面表示はしない。
 */
function lsc_password_policy_errors( $password, $user_login = '', $user_email = '' ) {
	$errors = array();
	$lower  = strtolower( $password );

	if ( mb_strlen( $password ) < 12 ) {
		$errors[] = 'パスワードは12文字以上にしてください。';
	}

	$common = array( 'password', 'passw0rd', '12345678', '123456789', 'qwertyuiop', 'wordpress', 'letmein' );
	if ( in_array( $lower, $common, true ) ) {
		$errors[] = 'よく使われるパスワードは使用できません。';
	}

	$needles = array( $user_login );
	if ( $user_email && false !== strpos( $user_email, '@' ) ) {
		$needles[] = strstr( $user_email, '@', true ); // メールアドレスの@より前
	}
	foreach ( $needles as $needle ) {
		if ( strlen( $needle ) >= 3 && false !== stripos( $password, $needle ) ) {
			$errors[] = 'ユーザー名やメールアドレスを含むパスワードは使用できません。';
			break;
		}
	}

	return $errors;
}

// プロフィール更新・ユーザー追加(管理画面)
add_action( 'user_profile_update_errors', function ( $errors, $update, $user ) {
	if ( empty( $user->user_pass ) ) {
		return; // パスワードを変更しない更新は対象外
	}
	$login = isset( $user->user_login ) ? $user->user_login : '';
	if ( $update && ! empty( $user->ID ) ) {
		$existing = get_userdata( $user->ID );
		$login    = $existing ? $existing->user_login : $login;
	}
	$email = isset( $user->user_email ) ? $user->user_email : '';

	foreach ( lsc_password_policy_errors( $user->user_pass, $login, $email ) as $i => $message ) {
		$errors->add( 'lsc_password_policy_' . $i, esc_html( $message ) );
	}
}, 10, 3 );

// パスワードリセット画面(wp-login.php?action=rp)
add_action( 'validate_password_reset', function ( $errors, $user ) {
	if ( ! ( $user instanceof WP_User ) || empty( $_POST['pass1'] ) ) {
		return;
	}
	// パスワードは記号を含むためサニタイズで変形させない。比較にのみ使う。
	$password = wp_unslash( $_POST['pass1'] );

	foreach ( lsc_password_policy_errors( $password, $user->user_login, $user->user_email ) as $i => $message ) {
		$errors->add( 'lsc_password_policy_' . $i, esc_html( $message ) );
	}
}, 10, 2 );

コードのポイント

user_profile_update_errors に渡される $user は保存前のデータで、パスワードを入力したときだけ user_pass に値が入ります。空なら検証を飛ばすことで、パスワード以外の項目を更新するたびにエラーが出るのを防いでいます。既存ユーザーの更新ではユーザー名が渡されないことがあるため、get_userdata() で取り直しています。

validate_password_reset はリセット画面を開いたときにも呼ばれ、その時点では $user がエラーオブジェクトのこともあるため、WP_User かどうかを先に確認しています。パスワードに sanitize_text_field() をかけると記号や空白が変わり、ユーザーが入力したものと違う値で判定してしまうので、ここでは wp_unslash() だけにとどめ、比較以外には使いません。パスワードを error_log() などで記録するのは避けてください。

よく使われるパスワードの一覧は例として短くしています。実運用では、公開されている頻出パスワードのリストから上位数千件をファイルに置き、読み込んで照合する方法もあります。

画面のヒント文を合わせる

パスワード欄の下に表示される標準のヒント文は、password_hint フィルターで変更できます。ルールと説明が食い違うとユーザーが迷うため、サーバー側のルールに合わせて書き換えておきます。

add_filter( 'password_hint', function () {
	return 'パスワードは12文字以上で、ユーザー名やメールアドレスを含まないものにしてください。長めの文章のようなパスフレーズもおすすめです。';
} );

このコードが効かない場面

WooCommerceのマイアカウントや会員プラグイン独自の登録・変更フォームは、標準とは別の処理でパスワードを保存していることがあり、上記のアクションを通らない場合があります。その場合は各プラグインが用意しているバリデーション用のフックを使うか、プラグイン側のパスワードルール設定を利用してください。また、WP-CLIや wp_set_password() を直接呼ぶ処理も検証の対象外です。

プラグインで設定する場合

コードを書かずに済ませたい、または有効期限や再利用禁止なども管理したい場合は、プラグインが選択肢になります(2026年10月現在)。

  • Melapress Login Security / Password Policy Manager(Melapress):権限グループごとに文字数・文字種などのルールを設定できる
  • Solid Security:パスワードの強度要件や、漏えい済みパスワードの拒否に関する機能を持つ
  • Wordfence:ログイン保護の設定に強いパスワードを求める項目がある

製品名や機能の範囲はたびたび変わるため、導入前に公式ページで現在の機能を確認してください。セキュリティプラグイン同士は機能が重なりやすいので、パスワードルールを担当するのは1つに絞り、ここで紹介したmu-pluginと併用する場合はルールが矛盾しないようにします。

まとめ

  • 標準の強度メーターは警告のみで、弱いパスワードの保存は止めない
  • ルールは文字種の強制より、長さとよく使われるパスワード・ユーザー名の拒否を重視する
  • user_profile_update_errors と validate_password_reset でサーバー側の検証を追加し、パスワードは比較以外に使わない
  • 独自フォームを持つプラグインは別途対応が必要で、二要素認証やログイン試行回数の制限と組み合わせて運用する

お気軽にご相談ください

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