WordPressのパスワードを別システムでも使いたいときの認証方法

「WordPressのユーザーを別のシステムに移行する」といった
ちょっと変わった案件に出くわした際のメモ。

パスワードもそのまま移行する仕様ですが、
新しいシステム側のログインチェック時にどうやって比較すれば良いのか、というのが疑問。

WordPressでのパスワードの暗号化(ハッシュ化)


そもそもWordPressのパスワードってどういう形で保存されているのだろう?

  • バージョン2.5以降:phpass
  • バージョン2.5より前:md5

ってことみたい。
バージョンの途中で変わっているようです。

ちなみに、phpassで保存されているかどうかは、DB内のパスワードを見て、
頭の三文字が$P$かどうかを見れば分かるっぽいです。

phpassって何?って方には、こちらの記事がオススメ。
なぜPHPアプリにセキュリティホールが多いのか?:第40回 MOPS:安全性の高いパスワードハッシュ作成ツール - phpass|gihyo.jp … 技術評論社

よりセキュアにってことみたいです。

暗号化:wp_hash_password()


wp-includes -> pluggable.php 内のwp_hash_password()がハッシュ化する関数になります。
requireしているclass-phpass.phpというのがphpassの本体です。

※ソースコードはWordPress 3.2.1から引用。

wp_hash_password()の戻り値がハッシュ化されたパスワードになります。
このパスワードがWordPressのデータベース、 wp_usersテーブルに格納されています。


/**
 * Create a hash (encrypt) of a plain text password.
 *
 * For integration with other applications, this function can be overwritten to
 * instead use the other package password checking algorithm.
 *
 * @since 2.5
 * @global object $wp_hasher PHPass object
 * @uses PasswordHash::HashPassword
 *
 * @param string $password Plain text user password to hash
 * @return string The hash string of the password
 */
function wp_hash_password($password) {
 global $wp_hasher;

 if ( empty($wp_hasher) ) {
  require_once( ABSPATH . 'wp-includes/class-phpass.php');
  // By default, use the portable hash from phpass
  $wp_hasher = new PasswordHash(8, TRUE);
 }

 return $wp_hasher->HashPassword($password);
}

パスワード比較:wp_check_password()


新しいシステムでは、、WordPressで管理されていたユーザパスワードと、
画面から入力されたパスワードを比較する必要がありました。

どうやって比較すればよいのでしょう。
pluggable.php 内のwp_check_password()を参考にしました。


上記の一行がチェックの処理です。

画面から入力された平文のパスワードと、
データベースに格納されているハッシュ化されたパスワードを、
このCheckPassword()に渡します。

戻り値を判断して、完了です。


関数内では、md5で保存されている場合は「phpassで一度保存し直す処理」が
チェック前に行われています。

/**
 * Checks the plaintext password against the encrypted Password.
 *
 * Maintains compatibility between old version and the new cookie authentication
 * protocol using PHPass library. The $hash parameter is the encrypted password
 * and the function compares the plain text password when encypted similarly
 * against the already encrypted password to see if they match.
 *
 * For integration with other applications, this function can be overwritten to
 * instead use the other package password checking algorithm.
 *
 * @since 2.5
 * @global object $wp_hasher PHPass object used for checking the password
 * against the $hash + $password
 * @uses PasswordHash::CheckPassword
 *
 * @param string $password Plaintext user's password
 * @param string $hash Hash of the user's password to check against.
 * @return bool False, if the $password does not match the hashed password
 */
function wp_check_password($password, $hash, $user_id = '') {
 global $wp_hasher;

 // If the hash is still md5...
 if ( strlen($hash) <= 32 ) {
  $check = ( $hash == md5($password) );
  if ( $check && $user_id ) {
   // Rehash using new hash.
   wp_set_password($password, $user_id);
   $hash = wp_hash_password($password);
  }

  return apply_filters('check_password', $check, $password, $hash, $user_id);
 }

 // If the stored hash is longer than an MD5, presume the
 // new style phpass portable hash.
 if ( empty($wp_hasher) ) {
  require_once( ABSPATH . 'wp-includes/class-phpass.php');
  // By default, use the portable hash from phpass
  $wp_hasher = new PasswordHash(8, TRUE);
 }

 $check = $wp_hasher->CheckPassword($password, $hash);

 return apply_filters('check_password', $check, $password, $hash, $user_id);
}
ちなみに、今回の案件では、WordPressのバージョンは2.5以降のはずのに、 パスワードはMD5で保存されていました。それで随分とはまりました。

コメント

このブログの人気の投稿

CKeditorの文字色と文字背景色を変えるボタンが出てこない。

HTMLのインデントを揃えたい時に使える整形サービス