2010-07-21 7 views
6

Ich habe eine cherrypy-Anwendung und auf einige der Ansichten, die ich starten möchte, erlauben nur bestimmten Benutzern, sie zu sehen, und senden Sie jemand anderen auf eine Seite mit Autorisierung erforderlich.Ein CherryPy Decorator für die Autorisierung schreiben

Gibt es eine Möglichkeit, dies mit einem benutzerdefinierten Dekorator zu tun? Ich denke, das wäre die eleganteste Option.

Hier ist ein einfaches Beispiel von dem, was ich tun möchte:

class MyApp: 
    @authorization_required 
    def view_page1(self,appID): 
     ... do some stuff ... 
     return html 

def authorization_required(func): 
    #what do I put here? 

können auch die authorization_required Funktion, wenn sie als Dekorateur akzeptieren Parameter wie allow_group1, allow_group2 genannt? Oder brauche ich einen separaten Dekorator für jede Gruppe?

+0

Alle diese sind möglich, aber welche Art von Authentifizierungssystem verwenden Sie. Oder planen zu verwenden? CherryPy hat ein paar Authentifizierungsmethoden eingebaut: http://www.cherrypy.org/wiki/BuiltinTools – Wolph

+0

Ich glaube nicht, dass ich etwas eingebautes verwenden möchte. Wir haben einige benutzerdefinierte Datenspeicher, die ich überprüfen muss usw. – Greg

Antwort

4

Ok, in diesem Fall Ihr Dekorateur würde wie folgt aussehen:

# without any parameters 
def authentication_required(f): 
    @functools.wraps(f) 
    def _authentication_required(*args, **kwargs): 
     # Do you login stuff here 
     return f(*args, **kwargs) 
    return _authentication_required 

# With parameters 
def authentication_required(*allowed_groups): 
    def _authentication_required(f): 
     @functools.wraps(f) 
     def __authentication_required(*args, **kwargs): 
      # Do you login stuff here 
      return f(*args, **kwargs) 
     return __authentication_required 
    return _authentication_required 
+2

Was macht @functools.wraps? Ist das in cherrypy eingebaut? – Greg

+0

Auch ich denke, ich gebe nur f (* args, ** kwargs) zurück, wenn das Login-Zeug erfolgreich war? Wenn der Benutzer andererseits nicht autorisiert ist, würde ich einen cherry.redirect anrufen, anstatt zurückzukehren? – Greg

+0

Ja, richtig. Und die 'functools.wraps' ist eine Methode, die das automatische Kopieren des Funktionsnamens, der Dokumente und anderer Daten beim Schreiben von Dekoratoren handhabt. Wenn Sie 'help (method)' auf einer dekorierten Methode ausführen, erhalten Sie die Originaldokumente. – Wolph

13

Sie wirklich nicht wollen, individuelle Dekorateure für CherryPy zu schreiben. Stattdessen möchten Sie ein neues Werkzeug schreiben:

def myauth(allowed_groups=None, debug=False): 
    # Do your auth here... 
    authlib.auth(...) 
cherrypy.tools.myauth = cherrypy.Tool("on_start_resource", myauth) 

Siehe http://docs.cherrypy.org/en/latest/extend.html#tools für weitere Diskussion. Dies hat mehrere Vorteile gegenüber eine benutzerdefinierte Dekorateur schreiben:

  1. Sie erhalten den Dekorateur kostenlos aus dem Tool: @cherrypy.tools.myauth(allowed_groups=['me']), und es bereits weiß, wie man nicht auf der gleichen Funktion cherrypy.exposed verprügeln.
  2. Sie können Tools entweder pro Handler (mit dem Dekorator), pro-Controller-Baum (über _cp_config) oder per-URI-Baum (in Config-Dateien oder dicts) anwenden. Sie können sie sogar mischen und über Dekoratoren ein Basismerkmal bereitstellen und dann ihr Verhalten in Konfigurationsdateien überschreiben.
  3. Wenn eine Konfigurationsdatei Ihre Funktion deaktiviert, bezahlen Sie nicht die Leistungseinbuße beim Aufrufen der Decorator-Funktion, nur um zu sehen, ob sie ausgeschaltet ist.
  4. Sie werden daran denken, ein "Debug" -Arg wie alle eingebauten Tools hinzuzufügen. ;)
  5. Ihre Funktion kann früher (oder später, wenn Sie das benötigen) als ein benutzerdefinierter Dekorator ausgeführt werden, indem Sie einen anderen "Punkt" auswählen.
  6. Ihre Funktion kann bei mehrere Hook-Punkte ausgeführt werden, falls erforderlich.
+0

Ich bin mir nicht sicher, ob dies für mich arbeiten würde, weil dieser Code den RoutesDispatcher (statt?) Der expose decorator verwendet. Ich bin mir nicht sicher, warum es so gemacht wurde. – Greg

+0

Welcher Dispatcher Sie verwenden, ist nicht wirklich ein Problem: Jeder Dispatcher, der seinen Wert (einschließlich der Routes) wert ist, wird mit Tools arbeiten. Der expose decorator tut nichts mehr als set 'method.exposed = True'. Dies ist wiederum für alle Dispatcher erforderlich und hat keinen Einfluss darauf, ob Tools funktionieren. Nehmen Sie es aus dem Mund des Pferdes: Werkzeuge sind der Weg, dies in CherryPy zu tun. – fumanchu

+0

Wohin wird das Code-Snippet gesendet? –