2026年5月24日

2026年5月24日

WordPressのパスワード更新手順|password_hash()とwp_set_password()の正しい使い分け

WordPressのユーザーパスワードを更新するとき、PHPの password_hash() を自分で呼んでデータベースに書き込む必要はありません。WordPress 6.8以降は、コアの wp_hash_password() が内部で password_hash() によるbcryptを使っており、wp_set_password()・wp_update_user()・WP-CLIを使えば、その仕組みに沿った形で保存されます。この記事では、WordPressのパスワードハッシュの現在の仕組みを押さえたうえで、管理画面が使えない場合も含めた安全な更新手順と、独自のパスワード変更フォームを作るときの注意点を説明します。

WordPressのパスワードハッシュの仕組み

WordPressはパスワードを平文では保存せず、wp_users テーブルの user_pass 列にハッシュ値を保存しています。この方式はバージョンによって変わってきました。

  • WordPress 6.7まで: phpassというライブラリによるハッシュが標準で、user_pass は $P$ で始まる文字列でした。
  • WordPress 6.8以降: wp_hash_password() がPHPの password_hash() を使ったbcryptに切り替わりました。保存される値は $wp$2y$ のように、先頭に $wp が付いた形になります。これは、bcryptに渡す前にパスワードを事前処理しているWordPress独自の形式であることを示す印です。

古い形式のハッシュがすぐに使えなくなるわけではありません。wp_check_password() は旧来のphpass形式も検証でき、そのユーザーが次にログインしたときに新しい形式へ自動で保存し直されます。このため、バージョンアップ後に全ユーザーのパスワードを一斉に変える必要はありません(2026年10月現在)。

ここから分かるのは、「パスワードのハッシュ化はWordPressの関数に任せるべき」ということです。password_hash() を自分で呼ぶと、WordPressが期待する形式とずれたり、将来のアルゴリズム変更に追従できなかったりします。

方法1: WP-CLIで更新する(推奨)

SSHが使えるなら、WP-CLIが最も手早く、間違いの入りにくい方法です。

# 対象ユーザーを確認
wp user list --fields=ID,user_login,user_email

# パスワードを更新(通知メールを送らない場合は --skip-email)
wp user update your-admin --user_pass='new-strong-password' --skip-email

コマンドに直接パスワードを書くとシェルの履歴に残るため、実行後に履歴から消すか、作業用の一時的なパスワードを設定してログイン後すぐに管理画面から変更する運用にします。

本人にパスワードを決めてもらいたい場合は、再設定用のメールを送るコマンドもあります。

wp user reset-password your-admin

メールが届かない環境(送信設定が未整備のサーバーなど)では、こちらは使えないので wp user update を使います。

方法2: PHPコードで更新する

WP-CLIが使えず、管理画面にも入れない場合は、WordPressを読み込んだPHPから更新します。使う関数は次の2つです。

  • **wp_set_password( $password, $user_id )**: 平文のパスワードを受け取り、ハッシュ化して user_pass を更新します。パスワード再設定用のキーも消去します。通知メールは送りません。
  • **wp_update_user()**: user_pass を含む配列を渡すと、同じくハッシュ化して保存します。パスワード変更の通知メールが送られ、更新対象がログイン中の本人であれば、ログイン状態を保ったままCookieを発行し直します。

管理画面に入れないときの一時的な手段として、mu-plugins に1回だけ実行するコードを置く方法があります。

<?php
// wp-content/mu-plugins/tmp-reset-password.php
// 1回読み込まれたら、すぐにこのファイルを削除すること
add_action( 'init', function () {
	$user = get_user_by( 'login', 'your-admin' );
	if ( $user ) {
		wp_set_password( 'temporary-strong-password', $user->ID );
	}
} );

このファイルを置いた状態でサイトを1回表示すると、パスワードが更新されます。置いたままにすると表示のたびにパスワードが上書きされ続けるため、ログインを確認したらすぐにファイルを削除し、管理画面から本番用のパスワードに変更してください。作業前にはデータベースのバックアップを取っておきます。

方法3: SQLで直接書き換える(最終手段)

phpMyAdminしか使えない場合の手段です。この方法では、WordPressの関数を通らないため、キャッシュの削除や関連フックの実行が行われません。まずデータベース全体をエクスポートしてから作業します。

ハッシュ値を自分で作れる環境(別のWordPressでWP-CLIが使えるなど)があれば、WordPress自身にハッシュを作らせるのが安全です。

wp eval 'echo wp_hash_password( "temporary-strong-password" ) . PHP_EOL;'

出力された値を、対象ユーザーの user_pass に設定します。

UPDATE wp_users
SET user_pass = 'ここに出力されたハッシュ値を貼り付ける'
WHERE user_login = 'your-admin';

古い解説でよく見る MD5('新しいパスワード') を直接入れる方法も、WordPressがログイン時にMD5を検証して新しい形式に保存し直すため、現在も動作はします。ただし、ログインするまでの間は弱いハッシュがデータベースに残ることになるので、使うとしても一時的な措置にとどめ、ログイン直後に管理画面からパスワードを変更します。

PHPの password_hash() で作った $2y$ で始まる素のbcrypt値を入れる方法は、WordPressの標準形式とは異なります。バージョンによって扱いが変わる可能性があるため、上の wp_hash_password() で作る方法を優先してください。

独自のパスワード変更フォームを作るとき

会員サイトなどでフロント側にパスワード変更フォームを置く場合は、権限確認・nonce・現在のパスワードの照合を省かないことが重要です。

add_action( 'admin_post_myplugin_change_password', 'myplugin_change_password' );

function myplugin_change_password() {
	if ( ! is_user_logged_in() ) {
		wp_die( 'ログインが必要です。', 403 );
	}
	check_admin_referer( 'myplugin_change_password' );

	$user    = wp_get_current_user();
	// パスワードは記号を含むため sanitize_text_field() は使わない
	$current = isset( $_POST['current_password'] ) ? wp_unslash( $_POST['current_password'] ) : '';
	$new     = isset( $_POST['new_password'] ) ? wp_unslash( $_POST['new_password'] ) : '';

	if ( ! wp_check_password( $current, $user->user_pass, $user->ID ) ) {
		wp_die( '現在のパスワードが正しくありません。', 400 );
	}
	if ( strlen( $new ) < 12 ) {
		wp_die( '新しいパスワードは12文字以上にしてください。', 400 );
	}

	wp_update_user( array(
		'ID'        => $user->ID,
		'user_pass' => $new,
	) );

	wp_safe_redirect( add_query_arg( 'password-changed', '1', home_url( '/mypage/' ) ) );
	exit;
}

フォーム側には wp_nonce_field( 'myplugin_change_password' ) と、action の値に myplugin_change_password を入れた hidden 項目を置き、送信先を admin_url( 'admin-post.php' ) にします。

ここでのつまずきどころは、パスワードの扱いです。sanitize_text_field() を通すと、前後の空白や一部の文字が取り除かれ、ユーザーが入力した値と保存される値が食い違います。パスワードは wp_unslash() だけにして、そのままハッシュ化する関数に渡します。また、wp_update_user() を使っているため、本人のログイン状態は保たれたまま、変更通知メールが送られます。

更新後に確認すること

  • ログインできるか: プライベートウィンドウで新しいパスワードでログインします。
  • ハッシュの形式: wp user get your-admin --field=user_pass で、6.8以降なら $wp$ で始まる値になっているかを確認できます。
  • 他の端末のセッション: 乗っ取り対応などでパスワードを変えた場合は、wp user session destroy your-admin --all で残っているセッションも破棄します。

まとめ

  • WordPress 6.8以降の wp_hash_password() は内部で password_hash() によるbcryptを使い、$wp$ で始まる独自形式で保存します。
  • 古いphpass形式のハッシュも検証でき、次回ログイン時に新形式へ保存し直されます。
  • パスワード更新はWP-CLIの wp user update --user_pass、またはPHPの wp_set_password()・wp_update_user() を使い、password_hash() を自分で呼ばないのが基本です。
  • SQLでの直接書き換えは最終手段とし、WordPressに作らせたハッシュを使い、事前にバックアップを取ります。
  • 独自フォームでは権限確認・nonce・現在のパスワードの照合を入れ、パスワードはサニタイズせず wp_unslash() だけにします。

お気軽にご相談ください

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