実行環境:
ruby 1.9.3
Rails 3.1.3
ログイン認証を実現する際、認証が必要なコントローラー内に before_filter を書いてコントローラーを実行する前にログイン状態をチェックします。ruby 1.9.3
Rails 3.1.3
たいてい、認証が必要なコントローラーが複数あります。それぞれに before_filter とそのメソッドを書くのはダサいので、before_filter を書いたコントローラークラスを作って継承させるのですが、認証させるコントローラーの数が多いと面倒になってきます。
すると「ええぃ、全てのコントローラーの親である ApplicationController に書いてしまえ!」と思うわけですが、逆に認証させたくないコントローラーが1つ2つあると、どうしてやろうか?と悩むことになります。
実現方法は色々あると思いますが、例としていくつかパターンを上げてみたいと思います。
ここでは例として
・CustomerController ⇒ 認証が必要(他にもいくつもある、という想定)
・LoginController ⇒ 認証が不要
という状況で説明してみようと思います。
① 認証用の before_filter を組み込んだコントローラーを作って継承させる(正攻法その1)
認証用の before_filter を組み込んだコントローラー(ここでは AuthController)を作り、認証が必要なコントローラーには AuthController を継承させます。
このような感じで継承させます。 ApplicationController ├─→ AuthController → CustomerController └──────────→ LoginController
以下がコードの大枠です。AuthController に認証の before_filter を仕込みます。
# ログインしていなければログイン画面へリダイレクト end endclass AuthController < ApplicationController before_filter :login_required private def login_required
class CustomerController < AuthController end
class LoginController < ApplicationController end
② 認証用のメソッドだけを ApplicationController で定義し、認証が必要なコントローラーだけで before_filter をセットする(正攻法その2)
before_filter にセットするプライベートメソッド(ここでは login_required)を ApplicationController で定義し、認証が必要なコントローラーには、個々のコードの中で before_filter をセットする。逆に認証不要なコントローラーにはセットしない。
継承関係はデフォルトのままです。 ApplicationController ├─→ CustomerController └─→ LoginController
以下がコードの大枠です。ApplicationController で認証用のプライベートメソッドのみを定義します。
# before_filter のセットは個々のコントロール内に書くのでここには書かない private def login_required # ログインしていなければログイン画面へリダイレクト end endclass ApplicationController < ActionController::Base
# 認証プロセスを踏ませる endclass CustomerController < ApplicationController before_filter :login_required
# 認証は不要なので、before_filter のセットはしない endclass LoginController < ApplicationController
③ 認証用の before_filter を ApplicationController に組み込み、認証が不要なコントローラー内で before_filter をスキップする
このような感じで継承させます。 ApplicationController ├─→ CustomerController └─→ LoginController
以下がコードの大枠です。ApplicationController に認証の before_filter を仕込み、LoginController 内で before_filter の適用をキャンセルします。
# ログインしていなければログイン画面へリダイレクト end endclass ApplicationController < ActionController::Base before_filter :login_required private def login_required
class CustomerController < ApplicationController end
# before_filter を適用しない endclass LoginController < ApplicationController skip_before_filter :login_required
LoginController 内に skip_before_filter を書いていますが、認証不要なクラスが複数ある場合は、skip_before_filter をつけた NoauthController クラスを作って、LoginController に NoauthController クラスを継承させるといいでしょう。
④ 認証用の before_filter を適用する・しないの条件付きで ApplicationController に組み込む
上記の②と似たようなやり方ですが、before_filter の適用・非適用の条件を ApplicationController 内で設定します。
②と同様、このような感じで継承させます。デフォルトのままですね。 ApplicationController ├─→ CustomerController └─→ LoginController
以下がコードの大枠です。ApplicationController に認証の before_filter を適用条件をつけて仕込みます。
# auth_target? が true の時のみ適用 private def login_required # ログインしていなければログイン画面へリダイレクト end def auth_target? self.controller_name != 'login' end endclass ApplicationController < ActionController::Base before_filter :login_required, :if => :auth_target?
class CustomerController < ApplicationController end
注意点としては、:if => の後ろはメソッドにしないといけません。直接 true や false を書いたり、true/false を返す式を書いてもエラーになります。 class LoginController < ApplicationController end
:unless も使えます。
before_filter の適用条件については前回まとめてます ⇒ [Rails3] before_filter に条件を設定する
namespace を使って(例えば :adminとか)認証の要る・要らないを分ける、というのもよくやられますね。あくまでも認証の要るもの要らないものを区別しているだけなので、実現するには実質的に上のどれかの方法を使うような形になると思います。
結論としては、めんどくさがりな人(=自分?)には④が楽ちんですが、お勧めは②です。
④と違って各コントローラー内のコードで認証の要る・要らないが判断できるのが良いと思います。
まあ、どういうやり方にするかは後は趣味の問題、かな。
0 件のコメント:
コメントを投稿