はじめに
前回2本立てと言いましたが、想像以上に内容が長くなったので、分割します。
とぅみまてぇん。
今回は問題集:初心者編の、
「Userモデルを作成して、email, password_digestを持たせる」
を進めていきます。
Userモデルを作成
RailsでUserモデルを作成します。
# Userモデルを作成(初期テーブルにemailとpassword_digestを追加)
rails g model User email:string password_digest:string
# DBに反映
rails db:migrate
Userモデルを作成したら、パスワードの暗号化とバリデーションを設定していきます。
# app/models/user.rb
class User < ApplicationRecord
has_secure_password
validates :email, presence: true, uniqueness: true
end
1つ1つ解説していきます。
パスワードを暗号化
ユーザーのパスワードを安全に守るためにハッシュ化します。
パスワードのハッシュ化について
ハッシュ化とは一方向性の変換です。
要は元のパスワードを全く別のものに変換することです。
なぜパスワードをハッシュ化する必要があるのか。
元のパスワードをわからなくして漏洩の被害を減らすため
もしデータベースが漏洩したときに、パスワードがそのまま保存されていたら不正アクセスし放題になります。
password: password123
それを防ぐためにハッシュ化で元のパスワードをわからなくすることで、
被害を減らすことができます。
元のパスワード: "password123"
ハッシュ化: "$2a$12$uYzqsf0cHF...GxHgGOzUwG9xNQ7K8mWT2ka"
ハッシュ化したものから元のパスワードを求めるのは非常に困難になります。
has_secure_password
これを使うことで次の機能が有効になります。
- passwordおよびpassword_confirmationという仮想属性が追加される。
(実際のカラムには存在しない)。 - password_digestというカラムに、passwordのハッシュを保存する。
- パスワードのバリデーション機能(例:空でないこと、確認との一致など)
- authenticateメソッドが追加され、パスワードの検証ができる。
authenticateとは?
認証用のメソッドで、主に「入力されたパスワードが正しいかどうか」を確認するためのもの。
user = User.find_by(email: "test@example.com")
if user&.authenticate("入力されたパスワード")
# 認証成功
else
# 認証失敗
end
また、has_secure_password(= BCrypt)は毎回異なるソルト(salt)というランダムデータを混ぜてハッシュ化します。
どういうことかというと、複数のユーザーが同じパスワードを使って登録しても、ハッシュ化の結果はランダムとなり被ることはありません。
これによりハッシュ化したパスワードが漏洩しても同じパスワードを使っていることがバレることはありません。
3人の元のパスワード: "password123"
1人目ハッシュ化: "$2a$12$uYzqsf0cHF...GxHgGOzUwG9xNQ7K8mWT2ka"
2人目ハッシュ化: "a$sld&ashdioh...gpjoaspojaspdojaspdjoakjsdojka"
3人目ハッシュ化: "&asdkjas234#...sdpgihjsdighsoiddfsplrkqweq34"
そして、ユーザーがログインするときは、入力されたパスワードを登録したときと同じ方法でハッシュ化することで、データベース内のハッシュ化パスワードと比較します。
バリデーションの設定
validates :email, presence: true, uniqueness: true
emailカラムに対してバリデーションの設定をしています。
パスワードはhas_secure_passwordで自動的にバリデーション設定されているので、記述する必要はなし。
- presence: true
空でないこと。(空文字やnilを許容しない) - uniqueness: true
他のユーザーと重複していないこと。
uniquenessはアプリケーションレベルでの検証です。厳密な一意性を保証するためには、DBのインデックスにユニーク制約を加えることも重要です。
By GPTえもん
以上でUserモデルの作成完了!!!!!
まとめ
パッと見た感じ、「あ、短そうだし2本立てでいっか!」と軽い感じで思っていたんですが、深掘っていくとめっちゃ重要な機能の追加だったので、長くなりすぎないように分割させていただきました。
次回は「SessionControllerを作成して、emailとpasswordでログインできるAPIを実装」を進めていきます。
ではまた。