1

すべてのユーザー認証コードを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に移動するだけで、リクエストなどにアクセスできるようになります(私は思います)。動作しますが、ヘルパーから地獄を乱雑にします。
  • すべての関数を別の場所に移動すると、それらのメソッドが表示されます(どこにあるかわかりません)
  • 私はただ何かが欠けているだけです。
4

1 に答える 1

4

一般的な 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

于 2009-06-16T16:32:49.197 に答える