2026年5月20日

2026年5月20日

WordPressのパスワード強度要件を設定する方法|最小文字数をPHPで強制する

WordPress の管理画面は、パスワードの強さをメーターで表示しますが、「弱いパスワードの使用を確認」(英語版では Confirm use of weak password)のチェックを入れれば、短いパスワードでも保存できます。会員サイトや複数人で運用するサイトで最小文字数などを守らせたい場合は、サーバー側(PHP)で検査して、条件を満たさないパスワードを拒否します。この記事のフックの動きは、2026年11月時点の WordPress のソースコード(wp-admin/includes/user.php と wp-login.php)で確認したものです。

どんな要件にするか

以前は「大文字・小文字・数字・記号をそれぞれ含める」といった要件がよく使われましたが、米国国立標準技術研究所(NIST)の電子認証のガイドライン SP 800-63B(第4版、2025年公開)は、考え方を次のように変えています。

  • パスワードだけでログインする場合は15文字以上、多要素認証と組み合わせる場合は8文字以上を求める
  • 64文字以上の長さを受け付ける
  • 文字の種類を混ぜる要件(構成ルール)は課さない
  • よく使われるパスワードや、漏えいしたことがわかっているパスワードの一覧(ブロックリスト)と照合して拒否する
  • 定期的な変更は求めない(漏えいの疑いがあるときは変更させる)

文字の種類を必須にすると、「Password1!」のような予測しやすい形に寄りやすいことがわかっています。この記事のコードは、最小文字数・ユーザー名やメールアドレスを含まないこと・よく使われるパスワードの拒否を基本にし、社内規程などで文字の種類が必要な場合に追加できる形にしています。

WordPress のどこでパスワードが設定されるか

画面 検査に使うフック
プロフィール画面・ユーザー編集画面での変更 user_profile_update_errors
「ユーザー → 新規追加」でのユーザー作成 user_profile_update_errors(新規作成のときは引数 $update が false)
ログイン画面の「パスワードをお忘れですか?」からの再設定 validate_password_reset

WordPress 標準の会員登録画面(wp-login.php?action=register)には、パスワードを入力する欄がありません。登録するとパスワード設定用のリンクがメールで届き、そこから上の表の「再設定」の画面で設定します。そのため、標準の登録画面について registration_errors フィルターでパスワードを検査する必要はなく、$_POST['pass1'] を検査するとかえって登録できなくなります。

検査するプラグインを作る

wp-content/mu-plugins/ フォルダー(無ければ作る)に password-policy.php という名前で保存すると、有効化の操作なしで読み込まれます。通常のプラグインとして wp-content/plugins/ に置いて有効化してもかまいません。テーマの functions.php に書くと、テーマを変えたときに検査が外れるので避けます。

<?php
/**
 * Plugin Name: Site Password Policy
 * Description: 管理画面とパスワード再設定で、弱いパスワードを拒否する。
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

const SITE_PW_MIN_LENGTH = 15; // 2段階認証を必須にしているなら 8〜12 でもよい

/**
 * パスワードの問題点をメッセージの配列で返す(問題が無ければ空の配列)。
 */
function site_pw_problems( $password, $login = '', $email = '' ) {
	$problems = array();

	if ( mb_strlen( $password, 'UTF-8' ) < SITE_PW_MIN_LENGTH ) {
		$problems[] = sprintf( 'パスワードは%d文字以上にしてください。', SITE_PW_MIN_LENGTH );
	}

	$lower = strtolower( $password );
	foreach ( array( $login, strstr( (string) $email, '@', true ) ) as $part ) {
		if ( is_string( $part ) && strlen( $part ) >= 3 && false !== strpos( $lower, strtolower( $part ) ) ) {
			$problems[] = 'パスワードにユーザー名やメールアドレスを含めないでください。';
			break;
		}
	}

	// よく使われるパスワードの例。最小文字数を下げた場合に効く。実際の運用では、漏えいパスワードの一覧などで増やす
	$blocklist = array( 'password', 'password123', 'passw0rd', '123456789', '1234567890', 'qwertyuiop', 'iloveyou', 'wordpress', 'administrator' );
	if ( in_array( $lower, $blocklist, true ) ) {
		$problems[] = 'よく使われるパスワードは使えません。';
	}

	// 規程で文字の種類が必要な場合だけ、次の2つを有効にする
	// if ( ! preg_match( '/[A-Z]/', $password ) || ! preg_match( '/[a-z]/', $password ) ) {
	// 	$problems[] = 'パスワードに大文字と小文字を含めてください。';
	// }
	// if ( ! preg_match( '/[0-9]/', $password ) ) {
	// 	$problems[] = 'パスワードに数字を含めてください。';
	// }

	return $problems;
}

/**
 * プロフィール変更・ユーザー編集・ユーザー新規追加。
 */
add_action( 'user_profile_update_errors', function ( $errors, $update, $user ) {
	if ( empty( $_POST['pass1'] ) ) {
		return; // パスワードを変えない更新
	}
	$password = trim( wp_unslash( $_POST['pass1'] ) );

	$login = isset( $user->user_login ) ? $user->user_login : '';
	$email = isset( $user->user_email ) ? $user->user_email : '';
	if ( $update && ! empty( $user->ID ) ) {
		$current = get_userdata( $user->ID );
		if ( $current ) {
			$login = $current->user_login;
		}
	}

	foreach ( site_pw_problems( $password, $login, $email ) as $i => $message ) {
		$errors->add( 'site_pw_' . $i, '<strong>エラー:</strong> ' . esc_html( $message ), array( 'form-field' => 'pass1' ) );
	}
}, 10, 3 );

/**
 * ログイン画面からのパスワード再設定。
 */
add_action( 'validate_password_reset', function ( $errors, $user ) {
	if ( empty( $_POST['pass1'] ) || ! ( $user instanceof WP_User ) ) {
		return;
	}
	$password = trim( wp_unslash( $_POST['pass1'] ) );

	foreach ( site_pw_problems( $password, $user->user_login, $user->user_email ) as $i => $message ) {
		$errors->add( 'site_pw_' . $i, '<strong>エラー:</strong> ' . esc_html( $message ) );
	}
}, 10, 2 );

コードのポイントは次のとおりです。

  • WordPress は $_POST の値の引用符などの前にバックスラッシュ(\)を足して扱うため、wp_unslash() で元の文字列に戻してから検査します。WordPress 本体も前後の空白を trim() で取り除いてから保存するので、同じように取り除きます。
  • パスワードは画面に表示したりログに書いたりしません。サニタイズ関数(sanitize_text_field() など)を通すと文字が変わることがあるので、検査だけに使います。
  • user_profile_update_errors でエラーを追加すると、保存されずに編集画面にエラーが表示されます。validate_password_reset でエラーを追加すると、再設定の画面にエラーが表示され、パスワードは変わりません。
  • 文字数は mb_strlen() で数えます。strlen() はバイト数を数えるので、日本語などを含むパスワードが実際より長く数えられます。

動作を確かめる

  1. ステージング環境に保存し、自分のプロフィール画面で短いパスワード(例: 10文字)を「弱いパスワードの使用を確認」にチェックを入れて保存し、エラーになることを確かめます。
  2. 15文字以上のパスワードで保存できることを確かめます。
  3. ログアウトして「パスワードをお忘れですか?」から再設定の画面を開き、同じ確認をします。

対象外になる場所

  • WP-CLI の wp user update --user_pass= や wp user create は、上のフックを通らないので検査されません。
  • WooCommerce の「マイアカウント」画面や、会員プラグインの独自の登録画面は、それぞれのプラグインのフックで検査を追加する必要があります。各プラグインのドキュメントで、パスワードを検査できるフックを確認してください。
  • すでに設定されている弱いパスワードは、この検査では見つかりません(WordPress はパスワードをハッシュで保存しているので、後から強さを調べられません)。次の一斉リセットで入れ替えます。

WP-CLI でパスワードを一斉にリセットする

不正アクセスが疑われるときや、新しい要件を導入したときは、wp user reset-password でパスワードを作り直せます。新しいパスワードはランダムに作られ、通常は利用者に変更の通知メールが送られます。

# 管理者全員のパスワードをリセットする(変更の通知メールが届く)
wp user reset-password $(wp user list --role=administrator --format=ids)

# 1人だけリセットし、メールは送らずに新しいパスワードだけを表示する
wp user reset-password editor01 --skip-email --porcelain

--show-password を付けると、新しいパスワードを画面に表示します。--porcelain はパスワードだけを出力します。表示したパスワードを本人に渡す場合は、チャットやメールの本文にそのまま貼らず、本人にログイン後すぐ変えてもらう運用にします。

パスワードの要件とあわせて、2段階認証を必須にする方法やログイン試行回数の制限も検討してください。

お気軽にご相談ください

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