如何禁用Django';s仅在某些情况下提供csrf保护?

如何禁用Django';s仅在某些情况下提供csrf保护?,django,api,csrf-protection,Django,Api,Csrf Protection,我正在尝试用Django编写一个站点,其中API URL与面向用户的URL相同。但是我在使用POST请求和CSRF保护的页面上遇到了问题。例如,如果我有一个页面/foo/add,我希望能够通过两种方式向其发送POST请求: 作为最终用户(使用会话cookie进行身份验证)提交表单。这需要CSRF保护 作为API客户端(使用HTTP请求头进行身份验证)。如果启用CSRF保护,则此操作将失败 我找到了各种禁用CSRF的方法,比如@CSRF_-emption,但是这些方法都会在整个视图中禁用它。有没有

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

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

  • 我找到了各种禁用CSRF的方法,比如@CSRF_-emption,但是这些方法都会在整个视图中禁用它。有没有办法在更细粒度的级别启用/禁用它?还是我必须从头开始实施自己的CSRF保护?

    Django的CSRF保护文档中有一节介绍了解决方案。我们的想法是在整个视图中使用
    @csrf\u export
    ,但当API客户端头不存在或无效时,则调用一个函数 用
    @csrf\u protect

    修改
    url.py
    如果在
    urls.py
    中管理路由,则可以将所需路由包装为,以将其从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()))
        # ...
    )
    
    from django.views.decorators.csrf import csrf_exempt
    from django.http import HttpResponse
    
    @csrf_exempt
    def my_view(request):
        return HttpResponse('Hello world')
    

    或者,作为一名装饰师 有些人可能会发现使用
    @csrf\u employ
    装饰器更适合他们的需要

    例如,

    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()))
        # ...
    )
    
    from django.views.decorators.csrf import csrf_exempt
    from django.http import HttpResponse
    
    @csrf_exempt
    def my_view(request):
        return HttpResponse('Hello world')
    

    如果您使用的是类基本视图(CBV),并且希望使用csrf_豁免装饰器,那么您将需要使用方法装饰器

    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
    

    你查过了吗?我读过一些,但显然没有读过所有的场景。谢谢你确定这个解决方案吗?