2010-07-21 13 views
6

J'ai une application cherrypy et sur certaines des vues je veux commencer seulement en permettant à certains utilisateurs de les voir, et en envoyant quelqu'un d'autre à une page d'autorisation requise.Écrire un CherryPy Decorator pour l'autorisation

Y at-il un moyen que je peux faire avec un décorateur personnalisé? Je pense que ce serait l'option la plus élégante.

Voici un exemple de base de ce que je veux faire:

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

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

peut également la fonction authorization_required lorsqu'il est appelé comme décorateur accepter des paramètres tels que allow_group1, allow_group2? Ou ai-je besoin d'un décorateur séparé pour chaque groupe?

+0

Tout cela est possible, mais quel type de système d'authentification utilisez-vous? Ou prévoyez d'utiliser? CherryPy a quelques méthodes d'authentification intégrées: http://www.cherrypy.org/wiki/BuiltinTools – Wolph

+0

Je ne pense pas que je veuille utiliser quoi que ce soit. Nous avons besoin de vérifier certains magasins de données personnalisés, etc. – Greg

Répondre

4

Ok, dans ce cas, votre décorateur ressemblerait à quelque chose comme ceci:

# 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

Que fait @ functools.wraps? Est-ce construit en cherrypy? – Greg

+0

Aussi, je suppose que je renvoie seulement f (* args, ** kwargs) lorsque les choses de connexion a réussi? Si d'autre part l'utilisateur n'est pas autorisé, est-ce que j'appellerais un cerise.redirect au lieu de retourner? – Greg

+0

Oui, c'est correct. Et le 'functools.wraps' est une méthode qui gère la copie automatique du nom de la fonction, docs et d'autres données lors de l'écriture des décorateurs. De cette façon, si vous faites 'help (méthode)' sur une méthode décorée, vous obtenez toujours les documents originaux. – Wolph

13

Vous ne voulez vraiment pas être écrire décorateurs personnalisés pour CherryPy. , Vous voulez plutôt que d'écrire un nouvel outil:

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

Voir http://docs.cherrypy.org/en/latest/extend.html#tools pour une discussion plus approfondie. Cela a plusieurs avantages par rapport à écrire un décorateur personnalisé:

  1. Vous obtenez le décorateur gratuitement à partir de l'outil: @cherrypy.tools.myauth(allowed_groups=['me']), et il sait déjà comment ne pas CLOBBER cherrypy.exposed sur la même fonction.
  2. Vous pouvez appliquer des outils soit par gestionnaire (avec le décorateur), soit par arborescence de contrôleurs (via _cp_config) ou par arborescence URI (dans les fichiers de configuration ou les dicts). Vous pouvez même les mélanger et fournir une fonction de base via les décorateurs, puis remplacer leur comportement dans les fichiers de configuration.
  3. Si un fichier de configuration désactive votre fonctionnalité, vous ne payez pas la pénalité liée aux performances en appelant la fonction décorateur juste pour voir si elle est désactivée.
  4. Vous vous souviendrez d'ajouter un argument 'debug' comme tous les outils intégrés. ;)
  5. Votre fonctionnalité peut être exécutée plus tôt (ou plus tard, si c'est ce dont vous avez besoin) qu'un décorateur personnalisé peut, en sélectionnant un "point" différent.
  6. Votre fonctionnalité peut s'exécuter à plusieurs points d'accrochage, si nécessaire.
+0

Je ne suis pas sûr si cela fonctionnerait pour moi parce que ce code utilise le RoutesDispatcher (au lieu de?) Le décorateur d'exposition. Je ne sais pas pourquoi cela a été fait de cette façon. – Greg

+0

Le répartiteur que vous utilisez n'est pas vraiment un problème: tout répartiteur digne de ce nom (y compris celui de Routes) fonctionnera avec les outils. Le décorateur expose ne fait rien de plus que mettre 'method.exposed = True'. Encore une fois, ceci est requis pour tous les répartiteurs et n'a aucune incidence sur le fait que les outils fonctionnent ou non. Prenez-le de la bouche du cheval: Les outils sont le moyen de le faire dans CherryPy. – fumanchu

+0

Où va l'extrait de code fourni? –