web-dev-qa-db-fra.com

@csrf_exempt ne fonctionne pas sur une classe basée sur une vue générique

class ChromeLoginView(View):

     def get(self, request):
          return JsonResponse({'status': request.user.is_authenticated()})

     @method_decorator(csrf_exempt)
     def post(self, request):
          username = request.POST['username']
          password = request.POST['password']
          user = authenticate(username=username, password=password)
          if user is not None:
                if user.is_active:
                     login(request, user)
                     return JsonResponse({'status': True})
          return JsonResponse({'status': False})

Je m'attends à ce que la publication soit stoppée par CSRF, mais elle renvoie une erreur 403.

Mais si enlevez ce décorateur et faites-le dans l'URLConf

url(r'^chrome_login/', csrf_exempt(ChromeLoginView.as_view()), name='chrome_login'),

ça va marcher.

Que s'est-il passé ici? est-ce que ça ne devait pas marcher, parce que j'imagine que c'est ce que method_decorator fait .. __

Tout conseil serait bon.

41
castiel

Vous devez décorer la méthode dispatch pour que csrf_exempt fonctionne. Ce qu'il fait est de définir un attribut csrf_exempt sur la fonction vue elle-même sur True, et le middleware vérifie cela sur la fonction vue (la plus à l'extérieur). Si seules quelques-unes des méthodes doivent être décorées, vous devez toujours utiliser csrf_exempt sur la méthode dispatch, mais vous pouvez utiliser csrf_protect sur ex. put(). Si une méthode HTTP GET, HEAD, OPTIONS ou TRACE est utilisée, elle ne sera pas vérifiée si vous la décorez ou non. 

class ChromeLoginView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super(ChromeLoginView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return JsonResponse({'status': request.user.is_authenticated()})

    def post(self, request):
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user is not None:
            if user.is_active:
                login(request, user)
                return JsonResponse({'status': True})
        return JsonResponse({'status': False})
63
knbk

Comme @knbk l'a dit, c'est la méthode dispatch() qui doit être décorée.

Depuis Django 1.9, vous pouvez utiliser le method_decorator directement sur une classe :

@method_decorator(csrf_exempt, name='dispatch')
class ChromeLoginView(View):

    def get(self, request):
        return JsonResponse({'status': request.user.is_authenticated()})

    def post(self, request):
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user is not None:
            if user.is_active:
                login(request, user)
                return JsonResponse({'status': True})
        return JsonResponse({'status': False})

Cela évite de surcharger la méthode dispatch() uniquement pour la décorer.

58
Antoine Pinsard

Si vous recherchez des Mixins correspondant à vos besoins, vous pouvez créer un CSRFExemptMixin et l'étendre, sans avoir à écrire les instructions ci-dessus dans chaque vue:

class CSRFExemptMixin(object):
   @method_decorator(csrf_exempt)
   def dispatch(self, *args, **kwargs):
       return super(CSRFExemptMixin, self).dispatch(*args, **kwargs)

Après cela, étendez ceci à votre avis comme ceci.

class ChromeLoginView(CSRFExemptMixin, View):

Vous pouvez étendre cela à n’importe quelle vue selon vos besoins, c’est réutilisabilité! :-)

À votre santé!

0
vikas0713