如何仅在某些情况下禁用 Django 的 csrf 保护?
Posted
技术标签:
【中文标题】如何仅在某些情况下禁用 Django 的 csrf 保护?【英文标题】:How can I disable Django's csrf protection only in certain cases? 【发布时间】:2012-07-07 15:09:16 【问题描述】:我正在尝试在 Django 中编写一个站点,其中 API URL 与面向用户的 URL 相同。但是我在处理使用 POST 请求和 CSRF 保护的页面时遇到了问题。例如,如果我有一个页面 /foo/add 我希望能够通过两种方式向它发送 POST 请求:
-
作为最终用户(使用会话 cookie 进行身份验证)提交表单。这需要 CSRF 保护。
作为 API 客户端(使用 HTTP 请求标头进行身份验证)。如果启用 CSRF 保护,这将失败。
我找到了各种禁用 CSRF 的方法,例如 @csrf_exempt,但这些都在整个视图中禁用它。有没有办法在更细粒度的级别启用/禁用它?还是我只需要从头开始实施自己的 CSRF 保护?
【问题讨论】:
你检查csrf protection docs了吗? 我已经阅读了一些内容,但显然没有阅读所有场景。谢谢! 【参考方案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)
【讨论】:
以上是关于如何仅在某些情况下禁用 Django 的 csrf 保护?的主要内容,如果未能解决你的问题,请参考以下文章
如何仅在 localhost 的 Spring Security 中禁用 csrf?