【问题标题】:@csrf_exempt does not work on generic view based class@csrf_exempt 不适用于基于通用视图的类
【发布时间】:2015-02-03 14:32:07
【问题描述】:
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})

我希望帖子确实被 csrf 停止,但它返回 403 错误。

但如果删除该装饰器并在 URLConf 中执行此操作

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

它会起作用的。

这里发生了什么?它不应该工作吗,因为我想那是 method_decorator 所做的。 我正在使用 python3.4 和 django1.7.1

任何建议都会很棒。

【问题讨论】:

  • 你应该看看 django_braces...
  • @rnevius 非常感谢,以前从不知道这个用于 django 的 mixin 库。
  • 太棒了!特别是因为您可以简单地将CsrfExemptMixin 添加到您的视图中以使其工作。这几乎就像作弊......
  • 在我的用例中,我没有使用表单,那么如何在我的应用程序中仍然包含 csrf 令牌?就像我正在创建 API,因此 UI 不会出现。那么如何确保 CSRF 令牌仍然通过?
  • 这些答案不适用于 DRF。见stackoverflow.com/questions/30871033/…

标签: python django


【解决方案1】:

Django braces 为此提供了一个CsrfExemptMixin

from braces.views import CsrfExemptMixin

class ChromeLoginView(CsrfExemptMixin, View):
    ...

【讨论】:

    【解决方案2】:

    正如@knbk 所说,这是必须装饰的dispatch() 方法。

    从 Django 1.9 开始,you can use the method_decorator directly on a class:

    from django.utils.decorators import method_decorator
    
    @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})
    

    这避免了重写 dispatch() 方法只是为了装饰它。

    【讨论】:

      【解决方案3】:

      如果您正在寻找符合您需求的 Mixin,那么您可以创建一个 CSRFExemptMixin 并在您的视图中扩展它,而无需在每个视图中编写上述语句:

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

      然后像这样在你的视图中扩展它。

      class ChromeLoginView(CSRFExemptMixin, View):
      

      您可以根据需要在任何视图中扩展它,这就是可重用性! :-)

      干杯!

      【讨论】:

        【解决方案4】:

        您需要装饰dispatch 方法以使csrf_exempt 工作。它所做的是将视图函数本身的csrf_exempt 属性设置为True,中间件会在(最外层的)视图函数上检查这个。如果只需要修饰几个方法,您仍然需要在dispatch 方法上使用csrf_exempt,但您可以在例如使用csrf_protect put()。如果使用了GETHEADOPTIONSTRACE HTTP 方法,则不会检查是否装饰它。

        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})
        

        【讨论】:

          猜你喜欢
          • 2014-01-08
          • 2016-08-06
          • 2023-03-14
          • 2012-11-15
          • 1970-01-01
          • 2018-08-21
          • 1970-01-01
          • 2011-11-14
          相关资源
          最近更新 更多