2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

has_secure_password でつくられたpassword_digestをBcryptで検証する

Last updated at Posted at 2021-01-30

概要

Railsでhas_secure_password パスワードの変更時に、「現在のパスワードを入力する」っていうやつをどうやってやろうかなーと思って、考えたことをメモする

具体的には、現在のパスワードがとpassword_digestを称号して、一致するなら 真となる値(trueなど)を返す方法です。

Deviseの人

deviseならば valid_password?を使ってください。

has_secure_passwordな人のやり方

db/migrate/20210129094437_create_users.rb
class CreateUsers < ActiveRecord::Migration[6.1]
  def change
    create_table :users do |t|
      t.text :password
    end
  end
end
app/models/user.rb
class User > ApplicationRecord
  has_secure_password
end

authenticateメソッドを使う

irb(main):001:0> user = User.new
   (0.4ms)  SELECT sqlite_version(*)
irb(main):002:0> user.password = 'hoge'
irb(main):003:0> user.password_digest
=> "$2a$12$kzeCnmviABPsc3hLDrLqWuXVFqp3Jweotl6jmWAOTv4YDhThEY/BW"
irb(main):004:0> user.authenticate_password('fuga')
=> false
irb(main):005:0> user.authenticate_password('hoge')
=> #<User id: nil, password_digest: [FILTERED]> # 一致した場合は自身を返す。 真となる。

BCrypt::Password#is_password?メソッドを使う

BCryptを直接叩いてもできます。参考にしたのhas_secure_passwordが定義されているモジュール内の下記のコードです。

irb(main):001:0> user = User.new
   (0.4ms)  SELECT sqlite_version(*)
irb(main):002:0> user.password = 'hoge'
irb(main):003:0> user.password_digest
=> "$2a$12$kzeCnmviABPsc3hLDrLqWuXVFqp3Jweotl6jmWAOTv4YDhThEY/BW" # この文字列を検証する
irb(main):009:0> password_digest = user.password_digest
irb(main):010:0> password_digest
=> "$2a$12$kzeCnmviABPsc3hLDrLqWuXVFqp3Jweotl6jmWAOTv4YDhThEY/BW"
irb(main):011:0> BCrypt::Password.new(password_digest).is_password?('fuga')
=> false # 一致しない
irb(main):012:0> BCrypt::Password.new(password_digest).is_password?('hoge')
=> true # 一致するので true

BCrypt::Password.new(password_digest).is_password?('hoge') が肝です。 password_digestの暗号化された文字列が 検証したい文字列('hoge')から暗号化する文字列と一致するかを検証しています。

おまけ

Rails 6以降のhas_secure_passwordpassword というattributeもしくは password_digest というカラム以外も使えます。 ( rails 5.2だと使えない 5.2のhas_secure_password

たとえば、 recovery_password という文字列を使う場合は、以下の通りです。

これは、便利だ。

app/models/user.rb
class User > ApplicationRecord
  has_secure_password :recovery_password, validations: false
end

所感

実は、パスワード管理 deviseしか使っていなかった。相談を機に調べたらとても勉強になった。
has_secure_passwordの中身を知ったらパスワードだけなら has_secure_passwordでいいかなーと思った。
devise・・・はまりどころが多いからできれば使いたくないーと思っていたので。

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?