EC-CUBE 2系から4系へ移行するとき、会員のパスワードは条件を満たせばそのまま引き継げます。鍵になるのは「旧サイトの AUTH_MAGIC を取得できるか」と「2系側のハッシュ形式を正しく把握できているか」の2点です。この2つが押さえられていれば、4系の ECCUBE_AUTH_MAGIC に同じ値を設定するだけで、会員は従来のパスワードでログインできます。
移行前に確認する2点
まず旧サイトのDBで、パスワードの保存形式を確認します。数件だけ見ると判断を誤るので、全件の分布を見ます。
SELECT LENGTH(password) AS len, COUNT(*) FROM dtb_customer
WHERE del_flg = 0 GROUP BY len;
40文字の16進数なら 2.11未満のSHA1形式、64文字なら 2.11以降の hash_hmac(SHA256) 形式です。あわせて salt カラムの有無と、値が入っている件数も見ておきます。
SELECT COUNT(*) FROM dtb_customer
WHERE del_flg = 0 AND (salt IS NULL OR salt = '');
salt カラムは 2.11 で追加されたものです。注意したいのは、2.4系から 2.11以降へバージョンアップしたサイトでは、salt が採番されるのはパスワードを変更した会員だけという点です。1つのDBに旧形式と新形式が混在するので、どちらか一方と決めつけないでください。
次に旧サイトの AUTH_MAGIC を調べます。定数として定義されていますが、バージョンによって置き場所が違います。
grep -r AUTH_MAGIC data/
2.4系は data/cache/mtb_constants.php(元は data/mtb_constants_init.php)、2.11以降はインストーラが書き出す data/config/config.php に入っています。2.4系はパッケージ同梱の既定値がそのまま使われている例も多く、mtb_constants テーブルにも保存されているため、実際に取得できないケースはそれほど多くありません。
なぜ引き継げるのか
2.11未満の2系は、パスワードを次の式で保存しています。
sha1($pass . ":" . AUTH_MAGIC)
2.4系ではこれが関数にまとまっておらず、会員登録・ログイン・パスワード変更・管理画面からの編集など十数箇所に同じ式がそのまま書かれています。2.11以降は SC_Utils::sfGetHashString() に集約され、salt を使う形に変わりました。
hash_hmac(PASSWORD_HASH_ALGOS, $str . ":" . AUTH_MAGIC, $salt)
そして4系の PasswordHasher::verify() には、この両方を受け付ける分岐が今も残っています。
// 旧バージョン(2.11未満)からの移行を考慮
if (empty($salt)) {
$hash = sha1($plainPassword.':'.$this->auth_magic);
} else {
$hash = $this->hash($plainPassword, $salt);
}
salt が空なら 2.11未満と同じ sha1、salt があれば hash() に回します。その hash() の中身は hash_hmac($this->password_hash_algos, $plainPassword.':'.$this->auth_magic, $salt) で、2.11以降の sfGetHashString() と完全に同じ式です。salt の有無で新旧を判別し、どちらの形式もそのまま照合できる作りになっています。
さらに4.3以降は security.yaml で migrate_from が設定されており、旧形式でログインが成功すると新形式へ自動的に再ハッシュされます。
Eccube\Entity\Customer:
algorithm: 'auto'
migrate_from:
- legacy
再ハッシュ先の algorithm: 'auto' は Symfony 標準の bcrypt や argon2id で、hash_hmac ではありません。会員が一度ログインすれば、以降はそちらの形式で保存されます。
4.0〜4.2 は security.yaml が encoders 指定のままで、PasswordEncoder::needsRehash() が false を返すため自動再ハッシュは起きません。照合のロジック自体は同じものが PasswordEncoder::isPasswordValid() に入っているので、ログインは問題なくできます。旧形式のまま残り続けるだけです。
設定するのは AUTH_MAGIC だけ
データ移行時は dtb_customer の password をそのままコピーします。あわせて salt カラムもコピーしてください。2.11以降に登録・変更された会員は、salt が揃っていないと照合できません。2.11未満のまま残っている会員は salt が空のままで構いません。
あとは4系の .env に旧サイトと同じ値を書きます。
ECCUBE_AUTH_MAGIC=<旧サイトのAUTH_MAGICの値>
この値を変えると、移行した会員がログインできなくなります。新規構築なら任意の文字列で構いませんが、2系からの移行では旧サイトの値を使う必要があります。運用が始まってから変更することもできません。
salt を使う形式が含まれる場合は、ハッシュアルゴリズムも揃っている必要があります。4系の既定値は eccube.yaml の eccube_password_hash_algos で SHA256、2系も 2.11以降のインストーラが sha256 を優先して選ぶので、通常はそのまま一致します。hash_hmac のアルゴリズム名は大文字小文字を区別しないため、SHA256 と sha256 の表記差は問題になりません。旧サイトの data/config/config.php で PASSWORD_HASH_ALGOS を確認し、sha1 や md5 になっていた場合だけ4系側を合わせます。
引き継げないケース
旧サイトの AUTH_MAGIC が取得できない場合は引き継げません。会員にパスワード再設定を案内することになるため、移行の見積もりを出す前に確認しておくべき項目です。会員数が多いサイトでは、この案内の手間そのものが移行のコストになります。
旧サイトの AUTH_TYPE が PLAIN になっている場合も別扱いです。この設定ではパスワードが平文で保存されています。4系にも同じ分岐は残っていますが、平文のまま移行するのは避けて、移行のタイミングでハッシュ化する段取りを組むべきです。
EC-CUBEに関するお問い合わせ
[重要]現在公式にセキュリティサポートが切れていないPHPは8.1以上、MySQLは8.0以上で、対応しているEC-CUBEバージョンは4.2以上です。古いEC-CUBEを使っている方は適切なタイミングでバージョンアップをご検討ください。