2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails 8】標準認証(Authentication)の「元の画面に戻る」仕組みをコードから読み解く

2
Posted at

はじめに

Rails 8から導入された強力な標準機能である「認証ジェネレータ(bin/rails generate authentication)」。
これまでDeviseなどの外部Gemに頼っていたログイン機能が、標準コマンド一発で生成できるようになりました。

この標準機能を使っていて、「ログイン必須のページに直接アクセスして弾かれた後、ログインするとちゃんと元々見たかったページに飛ばしてくれる」という親切な挙動(いわゆるフレンドリーフォワーディング)に気づいた方も多いのではないでしょうか。

「これって裏側でどうやってるの?」と気になり、Deviseのようなブラックボックスではなく、Rails 8が生成したコードから直接その仕組みを読み解いてみました。

裏側にあるのは authentication.rb

Rails 8で認証機能を生成すると、app/controllers/concerns/ ディレクトリ配下に authentication.rb というモジュールが自動生成されます。

実は、このファイルの中にフレンドリーフォワーディングの仕組みが非常にシンプルに書かれています。

ステップ1:弾かれた時に、行きたかったURLを「記憶」する

未ログインのユーザーが、ログイン必須の画面(例:/users/edit)にアクセスしたとします。この時、コントローラーのフィルターによって以下の request_authentication メソッドが呼ばれます。

# app/controllers/concerns/authentication.rb

def request_authentication
  # アクセスしようとしたURLをセッションに記憶する
  session[:return_to_after_authenticating] = request.url
  
  # ログイン画面へ強制リダイレクト
  redirect_to new_session_path
end

ここでやっていることは超シンプルです。
session[:return_to_after_authenticating] というサーバー側のロッカー(セッション)に、ユーザーが本来アクセスしたかったURL(request.url)をこっそり保存してから、ログイン画面へリダイレクトさせています。

ステップ2:ログイン成功後、記憶したURLを「取り出す」

その後、ユーザーが正しい情報を入力してログイン(セッションの作成)に成功すると、行き先を決定するために以下の after_authentication_url メソッドが呼ばれます。

# app/controllers/concerns/authentication.rb

def after_authentication_url
  session.delete(:return_to_after_authenticating) || root_url
end

この1行にRubyの美しさが詰まっています。

  1. session.delete を使って、先ほどロッカーに保存したURLを取り出しつつ、ロッカーを空にします(不要なデータが残り続けるのを防ぐため)。
  2. ||(or演算子)を使って、もしロッカーが空だった場合(直接ログイン画面にアクセスしてきた場合など)は、デフォルトの root_url(トップページ)にフォールバックさせます。

最終的にログインのコントローラーは、このメソッドが返したURLに向かって redirect_to を実行しているだけなのです。

Rails 8 標準認証の最大のメリット

今回コードを読んでみて気づいた、Rails 8標準認証の最大のメリットは**「ブラックボックスがないこと」**です。

例えば、「うちのアプリは、どこからログイン画面に来たとしても、ログイン後は絶対にマイページ(/mypage)に飛ばしたい」という仕様変更があったとします。

もし巨大なGemを使っていたら、設定ファイルを書き換えたり、複雑なオーバーライドを調べる必要があります。しかしRails 8なら、自分の手元にあるコードを以下のように1行書き換えるだけで済みます。

# 変更前
def after_authentication_url
  session.delete(:return_to_after_authenticating) || root_url
end

# 変更後(強制的にマイページへ)
def after_authentication_url
  session.delete(:return_to_after_authenticating)
  mypage_url # 常に行き先を固定
end

おわりに

便利な機能に出会った時、一旦立ち止まって
「これがない時代はどうやって実装していたんだろう?」
「裏側ではどんなコードが動いているんだろう?」
と疑い、ソースコードを直接読みにいくことで、Webシステム全体の解像度がグッと上がります。

Rails 8の認証コードは非常に読みやすくまとまっているので、Rubyの勉強としても一度 app/controllers/concerns/authentication.rb を上から下まで読んでみることをおすすめします!

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?