2010-07-21 18 views
6

Mam aplikację cherrypy i na niektórych widokach, które chcę uruchomić, pozwalając tylko niektórym użytkownikom na ich przeglądanie i wysyłanie kogokolwiek na stronę wymaganą autoryzacji.Pisanie dekoratora CherryPy do autoryzacji

Czy mogę to zrobić za pomocą niestandardowego dekoratora? Myślę, że byłaby to najbardziej elegancka opcja.

Oto prosty przykład tego, co chcę zrobić:

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

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

Również Czy authorization_required gdy funkcja zwana jako dekorator akceptować parametry jak allow_group1, allow_group2? Czy potrzebuję osobnego dekoratora dla każdej grupy?

+0

Wszystkie te są możliwe, ale jakiego rodzaju systemu uwierzytelniania używasz. A może planujesz używać? CherryPy ma kilka wbudowanych metod uwierzytelniania: http://www.cherrypy.org/wiki/BuiltinTools – Wolph

+0

Nie sądzę, żebym chciał użyć cokolwiek wbudowanego. Mamy pewne niestandardowe magazyny danych, które muszę sprawdzić, itp. – Greg

Odpowiedz

4

Ok, w takim razie Twój dekorator będzie wyglądać mniej więcej tak:

# 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

Co robi funkcja @ functools.wraps? Czy to jest wbudowane w cherrypy? – Greg

+0

Sądzę też, że zwracam tylko f (* args, ** kwargs), gdy rzeczy do logowania się powiodły? Jeśli z drugiej strony użytkownik nie jest autoryzowany, czy powinienem zadzwonić do cherry.redirect zamiast zwrócić? – Greg

+0

Tak, zgadza się. A "functools.wraps" to metoda, która obsługuje automatyczne kopiowanie nazwy funkcji, dokumentów i innych danych podczas pisania dekoratorów. W ten sposób, jeśli zrobisz 'help (method)' na dekorowanej metodzie, nadal otrzymasz dokumenty oryginałów. – Wolph

13

Naprawdę nie chcę być pisanie niestandardowych dekoratorów dla CherryPy. Zamiast tego, chcesz pisać nowe narzędzie:

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

Zobacz http://docs.cherrypy.org/en/latest/extend.html#tools więcej dyskusji. Ma to kilka zalet w porównaniu pisania niestandardowego dekoratora:

  1. Otrzymasz dekorator za darmo z narzędzi: @cherrypy.tools.myauth(allowed_groups=['me']), a on już wie, jak nie sprać cherrypy.exposed na tej samej funkcji.
  2. Możesz zastosować narzędzia albo na operatorze (z dekoratorem), na drzewie kontrolera (przez _cp_config) lub na drzewo URI (w plikach konfiguracyjnych lub dyktach). Można je nawet miksować i udostępniać podstawową funkcję za pomocą dekoratorów, a następnie zastępować ich zachowanie w plikach konfiguracyjnych.
  3. Jeśli plik konfiguracyjny wyłączy funkcję, nie zapłacisz za wykonanie funkcji wywoływania funkcji dekoratora tylko po to, aby sprawdzić, czy jest wyłączona.
  4. Pamiętaj, aby dodać argument "debugowania", tak jak wszystkie wbudowane narzędzia. ;)
  5. Twoja funkcja może działać wcześniej (lub później, jeśli tego potrzebujesz) niż niestandardowy dekorator, wybierając inny "punkt".
  6. Twoja funkcja może działać w wielu hakach, jeśli jest to konieczne.
+0

Nie jestem pewien, czy to by działało dla mnie, ponieważ ten kod używa RoutesDispatcher (zamiast?) Dekoratora expose. Nie jestem pewien, dlaczego tak się stało. – Greg

+0

Który z używanych przez ciebie usług dyspozytorskich naprawdę nie jest problemem: każdy dyspozytor warty swojej soli (w tym Routes) będzie współpracował z narzędziami. Dekorator expose nie robi niczego więcej niż ustawia "method.exposed = True". Ponownie jest to wymagane dla wszystkich dyspozytorów i nie ma wpływu na działanie Narzędzi. Weź to z końskiego pyska: Narzędzia są sposobem na zrobienie tego w CherryPy. – fumanchu

+0

Gdzie znajduje się udostępniony fragment kodu? –