Rails認証機能入門

認証機能って何?

プロ太先生、今まで作ってきた製品管理アプリなんですが、誰でも編集・削除できちゃうんですよね…

それは大問題だよね。例えば、君の日記が誰でも読めて、勝手に書き換えられたら嫌ですよね。

はい、、。LaravelではAuth::user()みたいな認証機能がありましたが、Railsでも似たような機能があるんですか?

もちろんあるよ!RailsにはLaravelのBreeze(ブリーズ)みたいに、認証機能を自動で作ってくれる便利なジェネレータがあるんだ。今日はそれを使って、「ログイン・ログアウト機能」を追加してみよう!

Step1: 認証機能の土台を作ろう

まずは、Rails付属の認証ジェネレータを使って基本機能を作るよ。

# 認証機能に必要なファイルを一括生成
$ bin/rails generate authentication

おお、これだけでいいんですか!Laravelだと composer require laravel/breeze してから php artisan breeze:install って感じでしたよね。

そうそう!Railsの場合は最初から入ってるから、追加インストールは不要なんだ。このコマンドで以下が自動生成されるよ。

  • Userモデル: ユーザー情報を管理(Laravelと同じ)
  • Sessionモデル: ログイン状態を管理
  • コントローラ群: ログイン・ログアウト処理
  • ビュー群: ログイン画面など

次に、データベースにテーブルを作ろう。

# データベースにusersテーブルとsessionsテーブルを作成
$ bin/rails db:migrate

これもLaravelの php artisan migrate と同じ感覚ですね!

Step2: 最初のユーザーを作成しよう

テーブルができたら、実際にユーザーを作ってみよう。Railsコンソールを使うよ。

# Railsコンソール(対話モード)を起動
$ bin/rails console

LaravelでいうTinkerですね!

その通り!コンソールが開いたら、ユーザーを作成しよう。

# 新しいユーザーを作成(エラーが出たら例外を投げる)
store(dev)> User.create! email_address: "you@example.org", password: "s3cr3t", password_confirmation: "s3cr3t"

ここでのPoint!!

  • create! の「!」= 「絶対に作る!失敗したらエラーを出して教えて!」なくても動くが実務ではつけるべき!!
  • password_confirmation = パスワードの確認入力(タイプミス防止)

LaravelのUser::create()と似てますが、パスワード確認が必要なんですね。

セキュリティを重視してるんだ。パスワードは自動でハッシュ化されるから、データベースには暗号化された状態で保存されるよ。

ここで、サーバーを再起動しよう!

# bcrypt gem(パスワード暗号化ライブラリ)を有効にするため再起動
$ bin/rails server

Step3: 認証機能を試してみよう

認証機能を設定したら、どうやって動作確認するんですか?

まずは、普通にアプリのトップページを開いてみよう。ブラウザで http://localhost:3000/ にアクセスしてみて。

あ!いきなりログイン画面が出てきました!

そう!認証ジェネレータは、デフォルトで「全てのページ」を認証必須にするんだ。つまり:

  • トップページ(/
  • 商品一覧(/products
  • 商品詳細(/products/1
  • 商品作成(/products/new

全部ログインしないと見られない状態になってるんだよ。

なるほど!だから、どのページにアクセスしてもログイン画面になるんですね。

その通り!試しに http://localhost:3000/products/new(商品作成ページ)にアクセスしても、同じログイン画面が出るはずだよ。さっき作ったメールアドレスとパスワードを入力してみよう。

ログインできました!これで製品の作成・編集ページにアクセスできるようになったんですね。

その通り!ブラウザがcookie(クッキー)という仕組みで認証情報を覚えているから、他のページに移動してもログイン状態が保持されるんだ。

Step4: ログアウト機能を追加しよう

次は、ログアウトボタンを追加しよう。app/views/layouts/application.html.erbを編集するよ。

<!DOCTYPE html>
<html>
  <!-- 省略 -->
  <body>
    <!-- ナビゲーションバー(全ページ共通のメニュー) -->
    <nav>
      <!-- ホームページへのリンク -->
      <%= link_to "Home", root_path %>
      
      <!-- ログイン済みの場合のみログアウトボタンを表示 -->
      <%= button_to "Log out", session_path, method: :delete if authenticated? %>
    </nav>

    <!-- メインコンテンツエリア -->
    <main>
      <%= yield %>  <!-- 各ページの内容がここに入る -->
    </main>
  </body>
</html>

ここでのポイント:

  • link_to = 「〇〇へのリンクを作って」
  • button_to = 「〇〇用のボタンを作って」
  • if authenticated? = 「もしログイン済みなら」
  • method: :delete = 「DELETEリクエストで送信」(ログアウト=セッション削除)

LaravelのBladeテンプレートの @auth ディレクティブと似てますね!

そうそう!authenticated? がLaravelの Auth::check() と同じ役割だよ。

Step5: 一部のページは認証なしでもOKにしよう

ストアの商品一覧や詳細ページは、お客さんが見られるようにしておきたいよね。

確かに!ネットショップで商品を見るのにログインが必要だったら、誰も買い物しませんね。

ということで、app/controllers/products_controller.rbを編集しよう。

class ProductsController < ApplicationController
  # index(一覧)とshow(詳細)は認証なしでもアクセス可能
  allow_unauthenticated_access only: %i[ index show ]
  
  # 以下省略...
end

ここでのPoint!!

  • allow_unauthenticated_access = 「認証なしアクセスを許可する」
  • only: %i[ index show ] = 「indexとshowアクションのみ」
  • %i[ ] = シンボルの配列を作る簡単な書き方([:index, :show]と同じ)

LaravelのMiddlewareで auth を特定のルートから除外するのと似てますね!

Step6: 認証状態に応じてリンクを出し分けよう

商品一覧ページ

app/views/products/index.html.erbで、ログイン済みの人だけに「新商品作成」リンクを表示しよう

<!-- ログイン済み の場合のみ新商品作成リンクを表示 -->
<%= link_to "New product", new_product_path if authenticated? %>

レイアウトファイル

さらに、app/views/layouts/application.html.erbにログインリンクも追加しよう。

<nav>
  <!-- ホームへのリンク -->
  <%= link_to "Home", root_path %>
  
  <!-- ログイン状態によってリンクを出し分け -->
  <%= link_to "Login", new_session_path unless authenticated? %>  <!-- 未ログインの場合 -->
  <%= button_to "Log out", session_path, method: :delete if authenticated? %>  <!-- ログイン済みの場合 -->
</nav>

ここがポイント!!

  • if authenticated? = 「ログイン済みなら表示」
  • unless authenticated? = 「ログインしていなければ表示」

app/views/products/show.html.erbも更新しよう!

<h1><%= @product.name %></h1>  <!-- 商品名を表示 -->

<!-- 一覧ページに戻るリンク(誰でも表示) -->
<%= link_to "Back", products_path %>

<!-- ログイン済みの場合のみ編集・削除機能を表示 -->
<% if authenticated? %>
  <!-- 編集ページへのリンク -->
  <%= link_to "Edit", edit_product_path(@product) %>
  
  <!-- 削除ボタン(確認ダイアログ付き) -->
  <%= button_to "Destroy", @product, method: :delete, data: { turbo_confirm: "Are you sure?" } %>
<% end %>

ここがポイント!!
data: { turbo_confirm: "Are you sure?" } = 削除前に確認ダイアログを表示

Laravel vs Rails の認証機能比較

最後に、LaravelとRailsの認証機能を比較してみたいです!

どちらも似たような機能があるんですね!でもアプローチが少し違う感じがします。

そう!Laravelは「Middleware」でフィルタリング、Railsは「Controller」で直接指定という違いがあるね。どちらも覚えやすいよ。

まとめ:今日学んだこと

今日の学習内容をまとめよう!

  1. 認証機能の基本設定
    • bin/rails generate authenticationで一括生成
    • bin/rails db:migrateでテーブル作成
  2. ユーザー作成
    • bin/rails consoleでRailsコンソール起動
    • User.create!でユーザー作成
  3. ログイン・ログアウト機能
    • authenticated?でログイン状態を判定
    • button_toでログアウト機能実装
  4. アクセス制御
    • allow_unauthenticated_accessで一部ページを認証なしで許可
    • ビューでif authenticated?を使って表示制御

ありがとうございました!これで安全な製品管理アプリができました。LaravelとRailsの違いも理解できて、とても勉強になりました!

セキュリティは開発の基本だから、しっかりマスターしておこうね。