質問

すべてのユーザー認証コードを1か所、つまりlib / auth.rbに配置しました。次のようになります。

lib / auth.rb

module Admin

  def do_i_have_permission_to?(permission)
    # Code to check all of this goes here
  end

end

このモジュールをアプリケーションヘルパーの一部として含めるため、これらの機能はすべてのビューで使用できます。

application_helper.rb

require 'auth'
module ApplicationHelper
  include Admin
  # other stuff here
end

また、アプリケーションコントローラーの一部としても含めるため、コントローラーも同様に関数を呼び出すことができます。

application.rb

require 'auth'
class ApplicationController < ActionController::Base
  include Admin
end

これまでのところ、とても良い。

問題は、私のアプリケーションが通常のWebアプリとは異なることです。具体的には、複数のユーザーが(同じブラウザーを使用して)同じコンピューターから同時にシステムにログインできます。私は、そのIPからログインしているすべての人を見てアクションの認証を行います。すべての人がそれを行うことができれば、合格します。

これが意味することは、管理者が何かをしたい場合、その管理者は最初に他の全員をログアウトさせる必要があるということです。しかし、管理者が行うすべてのことについて、管理者が承認の印を押してほしいのです。だから私に与えられた提案は、管理者が通常アクセスできない任意のページでユーザー名/パスワードのコンボを提供できるようにすることでした(たとえば、「ユーザーの編集」ページにはこれらの追加入力フィールドがあります)、認証ルーチンは確認してください。つまり、

Admin::do_i_have_permission_to?(permission)

現在のリクエストパラメータを取得する必要があります。 paramsは定義されていないため、コントローラーで使用するようにparams [:foo]を使用することはできません。同様にrequest.parameters [:foo]も機能しません。私の検索は明らかにしました:

  • 現在の検索パラメーターは現在のリクエストに含まれています
  • 現在のリクエストは現在のコントローラーにあります
  • 現在のコントローラーは現在のディスパッチャにあり、
  • 現在のディスパッチャがどこに保持されているかわかりません。

とは言っても、経験から、この多くのフープを飛び回っているとき、おそらく間違いをしていると思います。それを行う正しい方法は何ですか?私が検討したオプションは次のとおりです。

  • 現在auth.rbにあるすべての関数をApplicationHelperに移動するだけで、リクエスト(など)にアクセスできます。動作しますが、ヘルパーから地獄を散らかします。
  • すべての関数を別の場所に移動すると、それらのメソッドが表示されます(どこにあるかわかりません)
  • 私は単に何かが欠けているだけです。
役に立ちましたか?

解決

典型的なRailsアプリケーションでは、認証情報はパラメーターではなくアクティブセッションに保存されます。そのため、必要なことを行うヘルパーを作成するのは非常に簡単です。

ApplicationHelperに含まれるモジュールを作成するのは、かなり正統ではないようです。従来のアプローチは、この場合おそらくAuthenticationHelperと呼ばれる別個のヘルパーを作成することです。これは、必要なコントローラーに含めることができます。または、必要に応じてApplicationControllerにロードして、ユニバーサルに使用可能にすることもできます。

一般的に、ヘルパーには他のヘルパーを含めるべきではありません。特定のコントローラーに複数のヘルパーを単純にロードすることをお勧めします。

ヘルパーメソッドは、操作元のコントローラーコンテキスト内で宣言されたインスタンス変数に完全にアクセスできます。具体的には、これらはインスタンス変数のみ(@name)であり、ローカル変数(name)ではありません。ヘルパーメソッドは特定のビューに対しても実行されます。

さらに、少なくとも従来のWebベースのアプリの場合、ユーザーが同じ手順で資格情報を提供し、操作を実行する理由はわかりません。通常、プロセスはログインしてからアクションを個別に実行します。

ただし、各トランザクションが独立した操作であるAPIの場合、最も簡単なアプローチは、認証を処理する関連するリクエストパラメーターを引き出し、コントローラーインスタンス変数を確立してから、実行を続行することです資格情報が課す制約が与えられた特定のリクエスト。

この種のことで私が通常従うアプローチは、必要なチェックを実行できるApplicationController自体の認証構造に階層化することです。これらは保護されたメソッドです。

can_edit_userなどのヒープ全体をロールインするのは魅力的ですか?およびcan_create_group?これらはすぐに手に負えなくなります。汎用can_performのフックを挿入するのは簡単な設計ですか?またはhas_authority_to?操作と必要なパラメータが渡されるメソッド。

たとえば、非常に大まかな実装:

  class ApplicationController < ActionController::Base
  protected
    def has_authority_to?(operation, conditions = { })
      AuthenticationCheck.send(operation, conditions)
    rescue
      false
    end
  end

  module AuthenticationCheck
    def self.edit_user?(conditions)
      session_user == conditions[:user]
    end
  end

  class UserController
    # ...

    def edit
      @user = User.find(params[:id])

      unless (has_authority_to?(:edit_user, :user => @user))
        render(:partial => 'common/access_denied', :status => :forbidden)
      end
    rescue ActiveRecord::RecordNotFound
      render(:partial => 'users/not_found')
    end
  end

明らかに、繰り返しを避けて一貫性を高めるために、多くの権限チェックをbefore_filterブロックにロールインしたいでしょう。

リストバンドのユーザー認証システムなど、完全なフレームワークの例がさらに役立つ場合があります。

http://github.com/theworkinggroup/wristband/tree/master

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top