2009-06-16 6 views
1

Ich habe meinen gesamten Benutzer-Authentifizierungscode an einem Ort gespeichert, nämlich lib/auth.rb. Es sieht wie folgt aus:Abrufen der aktuellen Anfrage in Rails aus einer Datei in lib/

lib/auth.rb

module Admin 

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

end 

ich dieses Modul als Teil des Anwendungs ​​Helfer gehören, so sind diese Funktionen in allen Ansichten:

application_helper .rb

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

Und ich schließe es auch als Teil der App lication Controller, so die Regler ebenfalls die Funktionen aufrufen:

application.rb

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

So weit, so gut.

Das Problem ist, dass meine Anwendung nicht wie eine normale Webanwendung ist. Insbesondere kann mehr als ein Benutzer gleichzeitig auf demselben Computer angemeldet sein (mit demselben Browser). Ich mache die Authentifizierung für Aktionen, indem ich alle Leute betrachte, die von dieser IP angemeldet sind, und wenn sie es alle können, passiert es.

Was das bedeutet ist, dass, wenn ein Admin etwas tun will, dieser Admin alle anderen zuerst ausloggen muss, was ärgerlich ist. Aber wir wollen das Admin-Gütesiegel für alles, was der Admin tut. Der Vorschlag, der mir gegeben wurde, bestand also darin, dass der Administrator auf jeder Seite, auf die er normalerweise keinen Zugriff hätte (z. B. eine 'Benutzer bearbeiten' Seite hätte diese zusätzlichen Eingabefelder), die Benutzername/Passwort-Kombination eingeben würde überprüfen Sie das. Dies bedeutet

Admin::do_i_have_permission_to?(permission) 

muss an den aktuellen Anfrage-Parameter erhalten. Ich kann nicht einfach params [: foo] wie ich in einem Controller verwenden, weil params nicht definiert ist; Ähnlich request.parameters [: foo] wird auch nicht funktionieren. Meine Suche hat ergeben:

  • Die aktuellen Suchparameter in der aktuellen Anforderung sind,
  • Die aktuelle Anforderung ist im Stromregler,
  • Der Stromregler ist im aktuellen Dispatcher und
  • I bin mir nicht sicher, ob der aktuelle Dispatcher irgendwo aufbewahrt wird.
  • Das sagte, Erfahrung sagt mir, dass, wenn ich durch diese vielen Reifen spring, ich wahrscheinlich Doing It Wrong bin. Was ist der richtige Weg? Optionen, die ich in Betracht gezogen habe sind:

  • Verschieben Sie einfach alle Funktionen derzeit in auth.rb in die ApplicationHelper wo (ich denke) sie haben Zugriff auf die Anfrage und so. Funktioniert, aber verstopft den Helfer aus der Hölle.
  • Verschieben Sie alle Funktionen woanders werden sie diese Methoden sehen (Ich weiß nicht wo)
  • Ich bin einfach nur etwas fehlt.

Antwort

4

In einer typischen Rails-Anwendung werden Authentifizierungsinformationen in der aktiven Sitzung gespeichert, nicht die Parameter. Als solches ist es ziemlich einfach, einen Helfer zu schreiben, der tut, was Sie wollen.

Es scheint eher unorthodox, ein Modul zu erstellen, das dann in ApplicationHelper enthalten ist. Der traditionelle Ansatz besteht darin, einen separaten Helfer zu erstellen, der in diesem Fall wahrscheinlich AuthenticationHelper heißen würde. Dies kann dann in allen erforderlichen Controllern enthalten sein oder auf Wunsch in ApplicationController geladen werden, um es universell verfügbar zu machen.

Im Allgemeinen sollten Helfer keine anderen Helfer enthalten. Es ist besser, einfach mehrere Helfer in einen bestimmten Controller zu laden.

Hilfsmethoden haben vollen Zugriff auf alle Instanzvariablen, die innerhalb des Steuerungskontextes deklariert sind, von dem aus sie arbeiten. Um genau zu sein, sind dies nur Instanzvariablen (@name) und keine lokalen Variablen (name). Hilfsmethoden werden auch für eine bestimmte Ansicht ausgeführt.

Außerdem bin ich mir nicht sicher, warum ein Benutzer Anmeldeinformationen bereitstellen und eine Operation in demselben Schritt ausführen würde, zumindest für traditionelle webbasierte Anwendungen. Normalerweise ist der Prozess, um sich einzuloggen und dann eine Aktion separat durchzuführen. Im Fall einer API, bei der jede Transaktion eine unabhängige Operation ist, besteht der einfachste Ansatz jedoch darin, die relevanten Anforderungsparameter herauszuholen, die sich mit der Authentifizierung befassen, einige Controller-Instanzvariablen zu erstellen und dann mit der Ausführung fortzufahren die bestimmte Anforderung angesichts der Einschränkungen, die die Anmeldeinformationen auferlegen.

Der Ansatz, den ich normalerweise für diese Art von Sache befolge, ist das Schichten in einer Authentifizierungsstruktur im ApplicationController selbst, der die erforderlichen Prüfungen durchführen kann. Dies sind geschützte Methoden.

Während es verlockend ist, einen ganzen Haufen von ihnen wie can_edit_user zu rollen? und can_create_group? diese geraten sehr schnell außer Kontrolle. Es ist ein einfacheres Design, um einen Haken für eine allgemeine can_perform zu setzen? oder has_authority_to? Methode, der eine Operation und alle erforderlichen Parameter übergeben werden.

Zum Beispiel eine sehr grobe Umsetzung:

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 

Offensichtlich würden Sie wollen eine Menge der Berechtigungsprüfungen in before_filter Blöcke rollen Wiederholungen zu vermeiden und Konsistenz zu fördern.

Ein vollständiges Rahmen Beispiel könnte mehr helfen, wie das Benutzer-Authentifizierungssystem Armband:

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

+0

Ich hatte die Funktionalität in ein Modul getrennt, weil ich es wollte aus Sicht aufrufbar sein oder Controller (Ich habe das oben bearbeitet, um dies klarer zu machen) Ich tat wie vorgeschlagen und erstellt eine authentication_helper.rb-Datei mit allen oben genannten Funktionen, aber sie scheinen nirgendwo anders sichtbar zu sein. (Ich bekomme "NoMethodError" trotz "Helfer: Authentifizierung" in meinem Controller setzen) Für was es wert ist, der Grund, warum ich diese Funktionen möchte, so kann ich sie verwenden, wie Sie oben beschrieben haben, ich will nur sie verfügbar überall: Controller, Ansichten, Tests, etc. – Atiaxi

+0

Ah, alle meine authentication_helper.rb Funktionen waren in einem eigenen Modul (AuthenticationHelper) - Putting 'Include AuthenticationHelper' wo es geeignet ist, es überall hin zu arbeiten, danke! – Atiaxi

+0

Wenn Sie Hilfsmethoden möchten, die auch Controller-Methoden sind, benötigen Sie eine Reihe geschützter ApplicationController-Methoden, die mit dem Aufruf helper_method getaggt sind. Zum Beispiel: def is_user_admin? false Ende helper_method: is_user_admin? – tadman

Verwandte Themen