SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Railsの新機能を知ろう!

より強化されたRails 8.0の新機能──シンプルな認証機能とデプロイの簡略化

Railsの新機能を知ろう! 第3回

  • X ポスト
  • このエントリーをはてなブックマークに追加

シンプルな組み込みの認証機能(2)

認証機能の利用例

 具体的に認証機能を試してみます。サインアップ機能がないので、db/seeds.rbファイルにユーザーを1件のみ登録し、マイグレーションがまだならrails db:migrateコマンドを、そのあとにrails db:seedコマンドを実行します。Userモデルにはhas_secure_passwordメソッドが記述されているので、平文のパスワードを引数passwordで渡せば自動的にハッシュをpassword_digest属性に格納してくれます(第1回を参照)。

 なお、後でパスワードリセットを試す場合には、ここに記載するメールアドレスは実際に受信可能なものに変更するか、追加する必要があります。また、メール送信に使うAction Mailerをメール送信できるように構成する必要もあります。

リスト:db/seeds.rb
User.create(email_address: 'user@example.com', password: 'password')

[NOTE]Action Mailerの構成

 配布サンプルでは、Action Mailerは既定値のままとなっているので、メール送信は行えません。app/mailers/application_mailer.rbファイルのdefaultメソッドに有効な送信元メールアドレスを指定し(既定はfrom@example.com)、config/environments/development.rbファイルに、例えば以下の設定を追加してください。SMTPサーバなどはご自身の環境に合わせてください。

リスト:config/environments/development.rb
config.action_mailer.raise_delivery_errors = true
config.action_mailer.smtp_settings = {
  address: "SMTPサーバ",
  port: ポート番号,
  domain: "HELOドメイン"
}

 テスト用のページを、例えばauth#indexなどとして作成します。

% rails generate controller auth index

 indexのビューに、サインインしているユーザーのメールアドレスやサインアウト、サインインのリンクなどを追記します。

リスト:app/views/auth/index.html.erb
<% if authenticated? %>
    <p><%= Current.user.email_address %> としてサインインしています。</p>
    <%= link_to 'サインアウト', session_path, data: { turbo_method: :delete } %>
<% else %>
    <p>サインインしていません。</p>
    <%= link_to 'サインイン', new_session_path %>
<% end %>

 サインアウト時にはトップページにリダイレクトされるので、ルート定義ファイルのrootメソッドを以下のように有効にしておきます。

リスト:config/routes.rb
root "auth#index"

 アプリケーションをrails serverコマンドで起動し、ブラウザからトップページにアクセスします。サインインしていないので、Sessionコントローラーのnewアクションが呼び出されて、サインインページが表示されます。

図:サインインページ
図:サインインページ

 初期データとして登録したメールアドレスとパスワードでサインインすると、authenticated?メソッドによってサインインしているとして、メールアドレスとサインアウトのリンクが表示されます。

図:サインイン後のトップページ
図:サインイン後のトップページ

 サインアウトすると、再びサインインページになります。ここで「Forgot password?」リンクをクリックすると、Passwordコントローラーのnewアクションによりパスワードリセット申請フォームが表示されるので、メールアドレスを入力してボタンを押すとパスワードリセットメールが送信されます。

 なお、ここで入力するメールアドレスは、usersテーブルに登録されている(サインアップされている)もので、かつ受信が可能である必要があります。

図:パスワードリセット申請フォーム
図:パスワードリセット申請フォーム

 以下のメール(Subject: Reset your password)が到着します。テキストパート、HTMLパートともにリンクが1個設置されています。リンクの有効期限は15分となっています。

図:パスワードリセットメール
図:パスワードリセットメール

 リンクをクリックすると、パスワードリセットフォームが開くので、新しいパスワードを入力して[Save]ボタンをクリックすれば、変更が完了します。

図:パスワードリセットフォーム
図:パスワードリセットフォーム
図:パスワードリセット完了
図:パスワードリセット完了

Sessionsコントローラーを見てみる

 最後に、実装を少し覗いてみましょう。例えばサインインとサインアウトを司るSessionsコントローラー(app/controllers/sessions_controller.rb)は、以下のようになっています。

リスト:app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
  allow_unauthenticated_access only: %i[ new create ]	(1)
  rate_limit to: 10, within: 3.minutes, only: :create, with: -> { redirect_to new_session_url, alert: "Try again later." }	(2)

  def new	(3)
  end

  def create	(4)
    if user = User.authenticate_by(params.permit(:email_address, :password))
      start_new_session_for user
      redirect_to after_authentication_url
    else
      redirect_to new_session_path, alert: "Try another email address or password."
    end
  end

  def destroy	(5)
    terminate_session
    redirect_to new_session_path
  end
end

 (1)に記述されているallow_unauthenticated_accessメソッドは、前述のように認証が不要なアクションの指定です。ここでは、newアクションとcreateアクションが指定されています。これらのアクションは認証が必要なときに呼び出されるので、当たり前と言えます。

 (2)に記述されているrate_limitは、Rails 8.0で実装されたレート制限のメソッドです。パラメータで制限内容と制限時のレスポンスを指定します。

  • to、within:時間内のリクエスト数を制限(この場合は3分で10回)
  • only:制限対象のアクション(この場合はcreate)
  • with:レスポンス内容(この場合は"Try again later."メッセージとともにサインイン画面へリダイレクト)

 制限されると既定では「429 Too Many Requests」がレスポンスされますが、withパラメータで内容をカスタマイズできます。

 (3)はnewアクションで、サインイン画面を表示するだけです。(4)はcreateアクションすなわちサインインの実行で、指定されたメールアドレスとパスワードで認証(authenticate_by、has_secure_passwordメソッドによって利用できる)を実行し、成功すればセッションを開始して元のページ(after_authentication_url)にリダイレクトします。失敗時には、"Try another email address or password."メッセージとともにサインイン画面にリダイレクトします。

 (5)はdestroyアクションすなわちサインアウト処理です。セッションを破棄して、サインインページへリダイレクトします。

 ジェネレータによって生成される認証機能には、サインアップをはじめ、メール認証、SNS認証などはサポートされないので、そういった機能が必要な場合には自分で追加実装するか、あるいは従来からあるDiviseなどを利用することになります。ただしシンプルな分見通しは良いので、独自のカスタマイズを施す余地は十分にあると思われます。

次のページ
デプロイの簡略化

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Railsの新機能を知ろう!連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 山内 直(WINGSプロジェクト ヤマウチ ナオ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook <個人紹介>WINGSプロジェクト所属のテクニカルライター。出版社を経てフリーランスとして独立。ライター、エディター、デベロッパー、講師業に従事。屋号は「たまデジ。」。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/20812 2025/02/04 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング