38

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

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

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

4

4 回答 4

60

调整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')
于 2015-06-30T10:40:46.167 回答
32

Django 的 CSRF 保护文档中有一段标题为“视图需要保护一个路径”,它描述了一个解决方案。这个想法是@csrf_exempt在整个视图上使用,但是当 API 客户端标头不存在或无效时,然后调用一个用@csrf_protect.

于 2012-07-07T11:33:30.503 回答
5

如果您正在使用类基视图 (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
于 2019-12-18T09:33:03.410 回答
0

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

所以这就是我最终要做的。我覆盖了课堂上的initialize_request可用内容。APIView

class ClasssName(views.APIView):
    def initialize_request(self, request, *args, **kwargs):
        setattr(request, 'csrf_processing_done', True) 
        return super().initialize_request(request, *args, **kwargs)
于 2021-12-18T01:47:00.393 回答