2010-07-21 7 views
6

Ho un'applicazione cherrypy e su alcune delle viste che desidero iniziare solo consentendo ad alcuni utenti di visualizzarle e inviare qualcun altro a una pagina richiesta di autorizzazione.Scrittura di un decoratore CherryPy per autorizzazione

C'è un modo per farlo con un decoratore personalizzato? Penso che sarebbe l'opzione più elegante.

Ecco un esempio di base di ciò che voglio fare:

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

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

inoltre possibile la funzione authorization_required quando viene chiamato come decoratore accettare parametri come allow_group1, allow_group2? O ho bisogno di un decoratore separato per ogni gruppo?

+0

Tutti questi sono possibili, ma che tipo di sistema di autenticazione stai usando. O pensando di usare? CherryPy ha un paio di metodi di autenticazione incorporati: http://www.cherrypy.org/wiki/BuiltinTools – Wolph

+0

Non penso di voler usare qualcosa di built-in. Abbiamo alcuni archivi di dati personalizzati che devo controllare, ecc. – Greg

risposta

4

Ok, in questo caso il vostro decoratore sarebbe simile a questa:

# 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

Cosa fa @ functools.wraps? È costruito nella cherubia? – Greg

+0

Inoltre, suppongo che restituisco solo f (* args, ** kwargs) quando il login è riuscito? Se invece l'utente non è autorizzato, dovrei chiamare un cherry.redirect invece di tornare? – Greg

+0

Sì, corretto. E il 'functools.wraps' è un metodo che gestisce la copia automatica del nome della funzione, dei documenti e di altri dati durante la scrittura dei decoratori. In questo modo se fai 'help (metodo)' su un metodo decorato, ottieni comunque i documenti originali. – Wolph

13

Davvero non vuole essere la scrittura decoratori personalizzati per CherryPy. Invece, si vuole scrivere un nuovo strumento:

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

Vedi http://docs.cherrypy.org/en/latest/extend.html#tools per ulteriori discussioni. Questo ha diversi vantaggi rispetto a scrivere un decoratore personalizzato:

  1. Si ottiene il decoratore gratuitamente dallo strumento: @cherrypy.tools.myauth(allowed_groups=['me']), e sa già come fare a non clobber cherrypy.exposed sulla stessa funzione.
  2. È possibile applicare Strumenti per gestore (con il decoratore), albero per controller (tramite _cp_config) o albero per URI (nei file di configurazione o dicts). Puoi persino mescolarli e fornire una funzione di base tramite i decoratori e quindi eseguire l'override del loro comportamento nei file di configurazione.
  3. Se un file di configurazione disattiva la funzione, non si paga la penalità delle prestazioni per chiamare la funzione decoratore solo per vedere se è disattivata.
  4. Ti ricorderai di aggiungere un argomento di debug come tutti gli strumenti incorporati. ;)
  5. La tua funzione può essere eseguita prima (o più tardi, se è ciò di cui hai bisogno) rispetto a un decoratore personalizzato, selezionando un "punto" diverso.
  6. La funzione può essere eseguita su più punti di aggancio, se necessario.
+0

Non sono sicuro se questo funzionerebbe per me perché questo codice utilizza il RoutesDispatcher (invece di?) L'expose decorator. Non sono sicuro del perché sia ​​stato fatto in quel modo. – Greg

+0

Il dispatcher che utilizzi non è davvero un problema: qualsiasi dispatcher che valga la pena (compresi i percorsi uno) funzionerà con gli strumenti. Il decoratore di esposizione non fa altro che impostare 'method.exposed = True'. Ancora una volta, questo è richiesto per tutti i dispatcher e non ha alcuna influenza sul fatto che gli Strumenti funzionino o no. Prendilo dalla bocca del cavallo: gli strumenti sono il modo per farlo in CherryPy. – fumanchu

+0

Dove viene fornito lo snippet di codice? –

Problemi correlati