0
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 5 years have passed since last update.

【Rails】セキュアなパスワード【Rails Tutorial 6章まとめ】

Last updated at Posted at 2019-11-27

生のパスワードをデータベースに保存すると、セキュリティ上問題になる。
そこで、bcryptジェムとhas_secure_passwordメソッドを用いて、パスワードをハッシュ化して保存する。
ハッシュ化とは、Rubyのハッシュのことではなく、文字列をランダムな文字列に変換することである。
暗号化のようであるが、復元できないという点が違うらしい。

bcryptジェム

Gemfileにbcryptを追加する。

Gemfile.rb
gem 'bcrypt', '3.1.12'

bundle installしておく。

has_secure_passwordメソッドとpassword_digestカラム

Userモデルにhas_secure_passwordメソッドを追加する。

app/models/user.rb
class User < ApplicationRecord
  .
  .
  .
  has_secure_password
end

このメソッドを使用するためには、Userモデルにpassword_digestカラムが必要になる。
カラム追加用のマイグレーションファイルを作成する。

$ rails generate migration add_password_digest_to_users password_digest:string
db/migrate/[timestamp]_add_password_digest_to_users.rb
class AddPasswordDigestToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :password_digest, :string
  end
end

マイグレーションファイルの末尾をto_usersとし、カラム名と型を入れておくと、自動でadd_columnを追加してくれる。
$ rails db:migrateしておく。

テストの修正

この時点で、テストが失敗する。
has_secure_passwordには、仮想的な属性としてpasswordとpassword_confirmationが追加されており、これらにはバリデーションが設定されている。
Userモデル用のテストでは、setupでこれらの属性の値を指定していないため、テストが失敗する。

そこで、これを修正しておく。

test/models/user_test.rb
  def setup
    @user = User.new(name: "Example User", email: "user@example.com",
                     password: "foobar", password_confirmation: "foobar")
  end

テストをして、成功することを確認する。

パスワードの最小文字数

パスワードは必ず存在していなければならない。
また、パスワードは短すぎてもよくない。
そこで、存在性の検証と、最小文字数を制限するバリデーションを追加する。

まずはこれらについてテストを書く。

test/models/user_test.rb
 test "password should be present (nonblank)" do
    @user.password = @user.password_confirmation = " " * 6
    assert_not @user.valid?
  end

  test "password should have a minimum length" do
    @user.password = @user.password_confirmation = "a" * 5
    assert_not @user.valid?
  end

最小文字数は6文字とし、空白は無効である。
ここでは、多重代入を使って、@user.passwordと@user.password_confirmationの二つに、同時に文字列を代入している。

Userモデルのpasswordカラムに、存在性と文字数制限のバリデーションを追加する。

app/models/user.rb
class User < ApplicationRecord
  .
  .
  .
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }
end

テストをして、成功することを確認する。
なお、password_confirmationに対するバリデーションは不要のようである。

authenticateメソッド

has_secure_passwordメソッドをUserモデルに適応したことで、Userオブジェクト(インスタンス)に対してauthenticateメソッドを使用できるようになる。
password属性(カラム)に代入された生のパスワードは、bcryptによってハッシュ化され、password_digestに保存される。
authenticateメソッドは、生のパスワードを引数に取り、それをハッシュ化して、password_digestに保存されているハッシュ値と比較する。
比較した結果が正しければ、このメソッドは該当するUserオブジェクトを返す。

>> user.authenticate("foobar")
=> #<User id: 1, name: "Michael Hartl", email: "mhartl@example.com",
created_at: "2016-05-23 20:36:46", updated_at: "2016-05-23 20:36:46",
password_digest: "$2a$10$xxucoRlMp06RLJSfWpZ8hO8Dt9AZXlGRi3usP3njQg3...">

ログイン機能の実装には、このUserオブジェクトの論理値がtrueであることを利用するので、これに!!(bang bang)を使用して論理値に変換する。

>> !!user.authenticate("foobar")
=> true
0
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
0
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?