【问题标题】:How can I disable Django's csrf protection only in certain cases?如何仅在某些情况下禁用 Django 的 csrf 保护?
【发布时间】:2012-07-07 15:09:16
【问题描述】:

我正在尝试在 Django 中编写一个站点,其中 API URL 与面向用户的 URL 相同。但是我在处理使用 POST 请求和 CSRF 保护的页面时遇到了问题。例如,如果我有一个页面 /foo/add 我希望能够通过两种方式向它发送 POST 请求:

  1. 作为最终用户(使用会话 cookie 进行身份验证)提交表单。这需要 CSRF 保护。
  2. 作为 API 客户端(使用 HTTP 请求标头进行身份验证)。如果启用 CSRF 保护,这将失败。

我找到了各种禁用 CSRF 的方法,例如 @csrf_exempt,但这些都在整个视图中禁用它。有没有办法在更细粒度的级别启用/禁用它?还是我只需要从头开始实施自己的 CSRF 保护?

【问题讨论】:

  • 你检查csrf protection docs了吗?
  • 我已经阅读了一些内容,但显然没有阅读所有场景。谢谢!

标签: django api csrf-protection


【解决方案1】:

Django 的 CSRF 保护文档中有一个标题为 View needs protection for one path 的部分描述了一个解决方案。这个想法是在整个视图上使用@csrf_exempt,但是当API客户端标头不存在或无效时,然后调用一个函数 用@csrf_protect注解。

【讨论】:

    【解决方案2】:

    修改urls.py

    如果您在urls.py 中管理您的路由,您可以使用csrf_exempt() 包装您想要的路由,以将它们从CSRF 验证中间件中排除。

    例如,

    from django.views.decorators.csrf import csrf_exempt
    urlpatterns = patterns(
        # ...
        # Will exclude `/api/v1/test` from CSRF 
        url(r'^api/v1/test', csrf_exempt(TestApiHandler.as_view()))
        # ...
    )
    

    或者,作为装饰者

    有些人可能会发现使用@csrf_exempt 装饰器更适合他们的需求

    例如,

    from django.views.decorators.csrf import csrf_exempt
    from django.http import HttpResponse
    
    @csrf_exempt
    def my_view(request):
        return HttpResponse('Hello world')
    

    【讨论】:

      【解决方案3】:

      如果您正在使用类基视图 (CBV) 并希望使用 csrf_exempt 装饰器,则需要使用方法装饰器。

      from django.utils.decorators import method_decorator
      from django.views import View
      from django.views.decorators.csrf import csrf_exempt
      
      @method_decorator(csrf_exempt, name='dispatch')
      class MyView(View):
          def post(self, request):
              pass  # my view code here
      

      【讨论】:

      • 你确定这个解决方案吗?
      【解决方案4】:

      就我而言,我使用 JWT 身份验证和 csrf_token 来获取某些视图。由于某些我不知道的原因,csrf_exempt 在我将其设置为装饰器或将视图名称包装在 url 模式中时不起作用。

      所以这就是我最终要做的。我覆盖了APIView 类中的initialize_request

      class ClasssName(views.APIView):
          def initialize_request(self, request, *args, **kwargs):
              setattr(request, 'csrf_processing_done', True) 
              return super().initialize_request(request, *args, **kwargs)

      【讨论】:

        猜你喜欢
        • 2013-08-25
        • 2016-09-21
        • 2019-05-13
        • 1970-01-01
        • 1970-01-01
        • 2015-05-02
        • 2020-01-21
        • 1970-01-01
        • 2018-01-19
        相关资源
        最近更新 更多