Rails4: 古いdeviseのパスワードを新しいdeviseで使う方法

書く書く詐欺をして早1年。
久しぶりの投稿です。

やりたいこと

データ移行時に前のシステムのパスワードをそのまま使いたい、別のシステムで使っているパスワードとログインIDを今回作成するシステムでも使えるようにしたい。
みたいな話がたびたびあるんですが、暗号化されているパスワード情報を適当に突っ込んでログインできるようになるかというと当然そんなことはなく。。。

今回は、Rails3.1.3 + devise1.5.3のシステムで使っていたパスワードをRails4.2.6 + devise4.2.0で使えるようにしたお話です。

やったこと

とりあえず、暗号化されたパスワードを突っ込んでみる

これでできたら楽!
ってことで、とりあえず、deviseで作成されるencrypted_passwordというカラムを移行してみます。
結果。。。無理でした!

移行前のシステムで使っているハッシュ関数を調べる

そもそも使っているハッシュ関数は同じものなの?ということで調べてみます。
古いシステムのconfig/initializers/devise.rbの中をみると

  • 古いシステムのコード
# ==> Configuration for :encryptable
# Allow you to use another encryption algorithm besides bcrypt (default). You can use
# :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
# :authlogic_sha512 (then you should set stretches above to 20 for default behavior)
# and :restful_authentication_sha1 (then you should set stretches to 10, and copy
# REST_AUTH_SITE_KEY to pepper)
config.encryptor = :sha512

こうあります。SHA512使ってる。
移行後のシステムではデフォルトでは特に何も指定していなかったのですが、1行コメントが追加されてた。

  • 新しいシステムのコード
# Require the `devise-encryptable` gem when using anything other than bcrypt

これ。どうやらSHA512を使うにはdevise-encryptableをインストールする必要があるようなので、インストールする。続いて、

  • devise-encryptableのページの指示通りに各種設定。
  • password_saltを追加しろとある。
  • 移行前のDBを見るとpassword_saltがある。
  • これもパスワードの暗号化に使っているのでこれも移行後のシステムに移す。

この状態でログインできるか試す。。。。
結果。またまた無理でした。

暗号化に関係していそうな値を調べる

saltは移したので別で関係してそうなやつ。
きっとdevise.rbにあるに違いない。ということで探してみる。

  • 古いシステムのコード
# Setup a pepper to generate the encrypted password.
# config.pepper = "976f7a348937fc83cde89ae08cd220d7e162a59fdde36bfbc9b0ed0ca5a7fefb6265959174a864facc26ef2ae6d37f97a414363607bd597ce979bacd24052981"

ペッパーの設定があるので見てみるとどちらもコメントアウトされてました。
次。

  • 古いシステムのコード
# ==> Configuration for :database_authenticatable
# For bcrypt, this is the cost for hashing the password and defaults to 10. If
# using other encryptors, it sets how many times you want the password re-encrypted.
#
# Limiting the stretches to just one in testing will increase the performance of
# your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
# a value less than 10 in other environments.
config.stretches = Rails.env.test? ? 1 : 10

ストレッチングの回数の設定があるので、見てみるとテスト環境以外は10回になっていた。
移行後のシステムの設定を見ると。。。

  • 新しいシステムのコード
# ==> Configuration for :database_authenticatable
# For bcrypt, this is the cost for hashing the password and defaults to 11. If
# using other algorithms, it sets how many times you want the password to be hashed.
#
# Limiting the stretches to just one in testing will increase the performance of
# your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
# a value less than 10 in other environments. Note that, for bcrypt (the default
# algorithm), the cost increases exponentially with the number of stretches (e.g.
# a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation).
config.stretches = Rails.env.test? ? 1 : 11

1回増えてる。。。
なので、ここも10回で同じにしてあげます。

この状態でログインを試す。。。
結果。

成功!

まとめ

やったこととしては、暗号化の仕組みを合わせるっていうのと、使っている値を合わせるっていう普通のことなんですが、IDと生パスワード一覧のCSVを用意して移行するとか昔やってたので、覚書のような形で書きました。

参考

devise

devise-encryptable

関連記事

Ruby on RailsによるWEBシステム開発、Android/iPhoneアプリ開発、電子書籍配信のことならお任せください この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

週刊Railsウォッチ

インフラ

Rubyスタイルガイドを読む

BigBinary記事より

ActiveSupport探訪シリーズ