1
2

More than 1 year has passed since last update.

【devise】暗号化前後のパスワードが一致しているか判定するメソッド

Last updated at Posted at 2022-01-10

実現したいこと

Railsでdevise gemを使っている環境にて、暗号化前のパスワードが暗号化後のパスワードと一致しているか確認したい。
例えば、以下のようなケースです。

  • 「このパスワードで設定したはずだがログインできず、パスワードがちゃんと設定されてるか確認してほしい」という問い合わせに対して調査する場合
  • 有効期限を持たせた複数のパスワードを、過去履歴を含めてDBに保持しており、古いパスワードが入力された場合に「それは古いパスワードです」とアラートを出したい場合

deviseでは、パスワードは暗号化されDBに保存されているため、DBのレコードを参照するだけだと、元のパスワードがどんなものだったかわかりません。

解決方法

「入力されたパスワードを自力で暗号化したものでDBを検索する」という方法もありますが、そこまでしなくても一発でわかるvalid_password?メソッドがdeviseで用意されています。
レシーバにはActiveRecordインスタンス(パスワードが保存されたレコード)、引数に暗号化前のパスワードを指定します。

基本例

# ユーザが入力した"hogehoge"というパスワードが、id=1234のユーザのパスワードと一致するか確認したい場合
User.find(1234).valid_password?("hogehoge")
# => 戻り値はboolean

# paramsで渡ってきたpassword(暗号化前)が、id=1234のユーザに設定されたパスワードと一致するか確認したい場合
User.find(1234).valid_password?(params[:password])

応用例

ちょっと発展させた例です。
例えば、有効期限を持たせた複数のパスワードを、過去履歴を含めてUserPasswordモデルに保持しており、
古いパスワードが入力された場合に「それは古いパスワードです」とアラートを出したい場合

def old_password?(input_password)
 old_passwords = UserPassword.find(1234).where.not(expired_at: nil)
 old_passwords.any? {|old_pw| old_pw.valid_password?(input_password) }
end

redirect_to new_session_path, alert: "入力されたパスワードは有効期限が切れています" if old_password?(params[:password])

参考サイト

devise gemでは以下で定義されているようです。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2