1
1

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 1 year has passed since last update.

Railsでセキュアなパスワードを実装する方法[備忘録]

Posted at

セキュアなパスワードを実装する

ユーザ認証について

ユーザ認証は以下の手順で行われます。
  1. パスワードの送信。
  2. ハッシュ化(ハッシュ関数を使って入力されたデータを不可逆なデータにする。)
  3. データベース内のハッシュ化された値との比較

今回は特にパスワードのハッシュ化の実装について学んだことを残しておこうと思います。

has_secure_password

ハッシュ化されたパスワードを実装する時は、has_secure_passwordメソッドを使います。

このメソッドを使用すると以下のことができるようになります。

  1. ハッシュ化したパスワードを、データベース内のpassword_digestという属性に保存できるようになる。
  2. authenticateメソッドが使えるようになる。(引数に正しいパスワードを入力すると、正しいユーザ情報を返し、間違ったパスワードだとfalseを返すメソッド)

使用条件

・モデル内にpassword_digestという属性が含まれている。

というわけで、has_secure_passwordを使用するためにpassword_digestという属性をusersテーブルに追加していこうと思います。

password_digestカラム用の適切なマイグレーションを作る。

まずは、ハッシュ化したパスワードを保存するpassword_digestカラムのマイグレーションを生成します。
rails generate migration add_password_digest_to_users password_digest:string

こちらのコードで以下のファイルとマイグレーションが生成されます。

db/migrate/20221228005859_add_password_digest_to_users.rb
class AddPasswordDigestToUsers < ActiveRecord::Migration[6.0]
  def change
    add_column :users, :password_digest, :string
  end
end

to_usersを末尾につけることで,add_column以下のコードが自動生成されています。
to_カラム名を末尾につけると指定したテーブルに引数で渡したカラムを追加するコードを自動生成してくれます。

ここでデータベースにマイグレーションを実行しましょう。

rails db:migrate

実際にカラムが追加されているかDB Browser for SQliteで確認してみましょう。

スクリーンショット 2022-12-28 11.34.57.png

無事追加されていることができました。

ここまでで、password_digestカラムを生成することがでいきました。

has_secure_passwordを使うために

password_digestカラムを作成する以外にもやることはあります。has_secure_passwordを使用するためにはハッシュ関数が必要です。なのでハッシュ関数であるbcryptをインストールします。

Gemfileにbcryptを追加します。

Gemfile
gem `bcrypt` `3.1.13`
bundle install

これでハッシュ関数が使えるようになりました。
次に、いよいよhas_secure_passwordを使用していきます。

has_secure_passwordを使ってみる

has_secure_passwordはUserモデルに記述します。
user.rb
class User < ApplicationRecord
    before_save {self.email = email.downcase}
    validates :name, presence: true, length: {maximum: 50}
    VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
    validates :email, presence: true, length: {maximum: 255},
                            format: { with: VALID_EMAIL_REGEX },
                            uniqueness: { case_sensitive: true }
    has_secure_password #こちらを追加
end

has_secure_passwordの上のコードについてはこちらを参照ください。

これでhas_secure_passwordは実装されました。しかし、このままだとバリデーションとして不完全です。

has_secure_passwordメソッドでは仮想的なpassword属性とpassword_confirmation属性に対してバリデーションする機能が強制的についています。そのためそれらについてのバリデーションを追加する必要があります。

パスワードの最小文字数を設定する

ここでは、password属性とpassword_confirmation属性のバリデーションを作成していきます。

今回はの2点についてバリデーションします。

  • パスワードが空でないこと。
  • 最小文字数が6文字であること。

以下のコードをUserモデルに追加します。

validates :password, presence: true, length: { minimum:6 }

presence:は空でないことについて定義します。length:は長さです。minimum:オプションで最小の長さについて定義しています。

ユーザの作成と認証

では、最後にユーザの作成と認証を実際に行ってみます。

今回はrailsコンソールを使用します。

rails console
user = User.create(name: "Katsuki Sanada", email: "sana@icloud.com",
                 password: "111111", password_confirmation: "111111")
=> #<User id: 1, name: "Katsuki Sanada", email: "sana@icloud.com",
     created_at: "2022-12-28 01:36:13", updated_at: "2022-12-28 01:36:13", 
     password_digest: [FILTERED]>

これで、ユーザを作成することができました。

認証にはauthenticateメソットを使います。

rails console
user.authenticate("111111")
=> #<User id: 1, name: "Katsuki Sanada", email: "sana@icloud.com",
 created_at: "2022-12-28 01:36:13", updated_at: "2022-12-28 01:36:13",
 password_digest: [FILTERED]>

正しいパスワードを入力すると、しっかり登録したユーザを返してくれます。

間違ったパスワードを入れたらどうでしょうか?

rails console
user.authenticate("333333")
=>false

こちらはfalseを返してくれているので、認証は成功していると言えそうです。

まとめ

  • 安全なパスワード認証のためにはhas_secure_passwordを使う。
  • ポイントはハッシュ化。

今回の学習はとても刺激的だなぁと思いました。次の内容が楽しみです。

参考文献

[Railsチュートリアル](https://railstutorial.jp/chapters/modeling_users?version=6.0#sec-adding_a_secure_password)
1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?