セキュアなパスワードの追加
ログイン/ログアウト機能を実現するため、ユーザー登録時にパスワードを登録できるようにしましょう。パスワードをそのままテキストで保存することはセキュリティの面で安全ではないため、暗号化した上でパスワードを保存する必要があります。そのために、Railsが標準で提供するhas_secure_passwordメソッドを利用します。
まずはhas_secure_passwordをUserモデルに記述します。
class User < ApplicationRecord …(中略)… has_secure_password end
has_secure_passwordメソッドを利用するには、対象のテーブルにpassword_digestというカラムがあることが前提となります。また、最新のハッシュ関数を提供するbcryptというgemも必要となります。
usersテーブルにpassword_digestカラムを追加するためのマイグレーションファイルを作成しましょう。
$ bin/rails g migration add_password_digest_to_users password_digest:string
↓
Running via Spring preloader in process 7013 invoke active_record create db/migrate/20170119100814_add_password_digest_to_users.rb
マイグレーションを実行します。
$ bin/rails db:migrate
bcryptをインストールするためにGemfileのコメントアウトを以下の通り外しましょう。
…(中略)… # Use ActiveModel has_secure_password gem 'bcrypt', '~> 3.1.7' …(中略)…
bundleインストールします。
$ bin/bundle install
has_secure_passwordメソッドは対象のモデルにpassword、password_confirmation仮想属性を与え、usersテーブルにpasswordカラムが存在しているかのような振る舞いを定義します。has_secure_passwordメソッド内部では、パスワードの検証に関する最低限のバリデーションを以下の3点追加しています。
- create時のpasswordが存在するか
- passwordが存在する場合にpassword_confimationが存在するか
- 仮想属性のpasswordとpassword_confimationが一致するか
ここではより明示的にpasswordが空でないことを、「最小文字数が6文字であること」として定義し、対応するバリデーションを追加します。
class User < ApplicationRecord …(中略)… has_secure_password validates :password, presence: true, length: { minimum: 6 } end
ユーザー登録時のパスワード追加
has_secure_passwordメソッドを追加したので、ユーザー登録時のフォームにもパスワードとパスワード確認の入力ボックスを追加し、ユーザー登録時にパスワードを登録できるようにしましょう。
フォームのビューファイルにパスワードとパスワード確認の入力ボックスを追加します。
…(中略)… <div class="field"> <%= f.label :password %> <%= f.password_field :password %> </div> <div class="field"> <%= f.label :password_confirmation %> <%= f.password_field :password_confirmation %> </div> …(中略)…
このままでも問題なさそうですが、実際にユーザー登録しようとするとパスワードのバリデーションエラーで登録できません。なぜなら以前紹介したように、Usersコントローラーのuser_paramsメソッドに定義されているstrong parametersが、パスワードデータを受け付けるようになっていないからです。
user_paramsメソッドを以下のように変更しましょう。
…(中略)… # Never trust parameters from the scary internet, only allow the white list through. def user_params params.require(:user).permit(:name, :email, :password, :password_confirmation) end …(中略)…
これで無事にパスワードを指定して、ユーザー登録を行うことができるようになりました。説明は割愛しますが、/users/newにアクセスしてパスワードを指定し、ユーザー登録できることを確認してみてください。