ユーザのパスワード用カラムを実装
ユーザ登録の際に「パスワード」、「パスワード(確認用)」を入力してもらいログインの際の認証用パスワードとして使いますが、
その登録画面での入力欄は単にテキストボックスを作っておけばよいというわけではなく、
・パスワード、パスワード(確認用)が一致すること
・パスワードによって関連付けられたユーザが認証できること
が必要となります。
Ruby on Railsではそれらの機能が簡単に(てっても初心者にはややこしいんですが)導入できるGEMがあるので、導入したときの手順を記載します。
なお、ここでは
・Viewでのパスワード入力欄
・ユーザログインプロセスの実装
の実装は含めておらず、
・ユーザモデルへのパスワード用カラムの実装
・パスワードをデータベースにハッシュ化して保存
・コンソール上でのユーザ認証
ができるところまで行っています。
前提
使用するモデル
ユーザのモデル名は「User」とし、下記の構成とする。
パスワード欄を実装していない状態で下記の「Users」テーブル構成。
カラム名 | 型 | 内容 |
---|---|---|
id | integer | モデル作成時に自動作成 |
name | string | ユーザ名(今回、直接は無関係) |
string | Email(今回、直接は無関係) | |
password_digest | string | ハッシュ化されたパスワード(今回の主役) |
手順
1.userモデルに"password_digest"カラムを追加
まずはマイグレーションファイルの作成
$ rails generate migration add_password_digest_to_users password_digest:string
とくにマイグレーションファイルをイジる必要はないのでざっと内容を確認したあとマイグレーション実行
$ rails db:migrate
2. gemの導入
Gemfileに下記行を追記して、文字列のハッシュ化を行ってくれるGEM「Bcrypt」をインストールする
gem 'bcrypt', '3.1.12' #パスワード(password_digest)をハッシュ化する
3. モデルへの暗号化機能の実装
モデルファイルに下記行を追記し暗号化機能を実装する
has_secure_password
上記を追記することで下記機能が実装される。
"password_digest"は開発者側で決めなくても自動的にこの名前が使われる。
3-1. セキュアにハッシュ化したパスワードを、データベース内のpassword_digestという属性に保存できるようになる。
実装したモデルのテーブル、この場合はUsersテーブルの"password_digest"というstring型のカラムにハッシュ化されたパスワードを保存できるようになる。
ただし"password_digest"カラムが自動的に追加されるわけではないので、手順1で実施したようにマイグレーションファイルの作成とマイグレーションの実行が必要となる。
3-2. 2つのペアの仮想的な属性 (passwordとpassword_confirmation) が使えるようになる。また、存在性と値が一致するかどうかのバリデーションも追加される。
"password"と"password_confirmation"は開発者側で決めなくても自動的にこの名前が使われる。データベースに保存されるカラムとしては存在しないが、モデル内の作業ではまるでデータベースにカラムが存在するように使用するため"仮想的"という言葉が使われている。
また、下記2点のバリデーションが自動的に追加される。
・"password"と"password_confirmation"が空白でないこと
・"password"と"password_confirmation"が同じ値であること
"password"("password_confirmation")の値をハッシュ化した文字列が1.の"password_digest"カラムに保存される。
3-3.authenticateメソッドが使えるようになる (引数の文字列がパスワードと一致するとUserオブジェクトを、間違っているとfalseを返すメソッド) 。
下記のような戻り値となる。
> user.authenticate('正しいパスワード')
=> #<User:0x00007f99c0698528
id: 101,
name: "User name",
email: "sample@email.com",
created_at: Wed, 21 Nov 2018 09:58:28 UTC +00:00,
updated_at: Wed, 21 Nov 2018 09:58:28 UTC +00:00,
password_digest: "$2a$10$W3f6EcZsP98/Yjjgh/li2OhucDRSombOCdzL7kQ2bdCNBBRrBR1le">
> user.authenticate('誤ったパスワード')
=> false
4. バリデーションの実装
バリデーションは実装しなくても動きはするが、セキュリティ性を考慮すると実装すべき
class User < ApplicationRecord
validates :password, presence: true, #空白は許可しない
length: {minimum: 6} #最低6文字必要とする
end