【问题标题】:Django Rest Framework complaining about CSRFDjango Rest Framework 抱怨 CSRF
【发布时间】:2015-11-30 15:44:43
【问题描述】:

我已经开发了一个简单的 web 服务,但是由于它抱怨 CSRF,所以无法在 Django Rest Framework 中使用 post:

"detail": "CSRF 失败:CSRF cookie 未设置。"

删除 api_view 装饰器确实会阻止消息出现,但是我将无法访问 request.data。 我认为 api_view 确实检查了 CSRF,尽管我添加了 csrf_exempt 装饰器。

这是我的看法:

@permission_classes((IsAuthenticated, ))
@csrf_exempt
@api_view(['POST'])
def get_stats(request):
    """
    Returns the stats available.
    """

    user = request.user

    if request.method == 'POST':
        serializer = StatsRequestSerializer(data=request.data)
        stats_request = serializer.data
        return JSONResponse(stats_request)

            #serializer = QuizSerializer(user.quizes.all(), many=True)
            #return JSONResponse(serializer.data)

    response = ActionResponse(status='error', error='Invalid request')
    serializer = ActionResponseSerializer(response)
    return JSONResponse(serializer.data, status=400)

这是我的模型:

class StatsRequest(models.Model):
    """
    A model which describes a request for some stats for specific users.
    """

    start_date = models.DateField()
    end_date = models.DateField()

这是我的请求 POST:

{"start_date" : "1992-01-15", "end_date" : "1992-01-15" }

有什么想法吗?

更多信息:

AUTHENTICATION_BACKENDS = (
    'social.backends.facebook.FacebookOAuth2',
    'social.backends.google.GoogleOAuth2',
    'django.contrib.auth.backends.ModelBackend'
)

【问题讨论】:

  • 对于每个 POST 请求,您都需要发送一个 crsf-token。在文档docs.djangoproject.com/en/1.7/ref/contrib/csrf/#csrf-ajax 中有更多关于此的信息
  • @Hinrich :这就是 csrf_exempt 装饰器的重点:绕过 csrf 验证,参见 docs.djangoproject.com/en/1.8/ref/csrf/…
  • 你试过没有csrf_exemptapi_view装饰器吗?您使用的是什么身份验证后端?
  • 我试过了,还是不行。我已经添加了我正在使用的身份验证后端。顺便说一句,对于这个特定的请求,我正在使用带有 cookie 的会话身份验证。

标签: python django csrf


【解决方案1】:

所以,在尝试了几个小时后,我终于做到了。 跟踪 DRF 和 Django 的源代码让我相信我需要为此找到解决方法,因为即使关闭 CSRF 验证也是明确进行的,可能是在 api_view 装饰器上进行 CSRF 检查。所以我只是创建了自己的装饰器:

from functools import wraps
from django.utils.decorators import available_attrs, decorator_from_middleware

def csrf_clear(view_func):
    """
    Skips the CSRF checks by setting the 'csrf_processing_done' to true.
    """

    def wrapped_view(*args, **kwargs):
        request = args[0]
        request.csrf_processing_done = True
        return view_func(*args, **kwargs)

    return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view)

以及我对新装饰器的看法:

@csrf_clear
@api_view(['POST'])
@permission_classes((IsAuthenticated, ))
def get_stats(request):
    """
    Returns the stats available.
    """

    user = request.user

    if request.method == 'POST':
        serializer = StatsRequestSerializer(data=request.data)

        if serializer.is_valid():
            stats_request = serializer.data
            return JSONResponse(stats_request)

            #serializer = QuizSerializer(user.quizes.all(), many=True)
            #return JSONResponse(serializer.data)

    response = ActionResponse(status='error', error='Invalid request')
    serializer = ActionResponseSerializer(response)
    return JSONResponse(serializer.data, status=400)

【讨论】:

    【解决方案2】:

    请看这个链接:
    Disabling CSRF checking in Django

    【讨论】:

    • 谢谢,但问题仍然存在,有什么想法吗?如前所述,那个 api_view 是这里的麻烦。
    【解决方案3】:

    urls.py

    from django.views.decorators.csrf import csrf_exempt
    urlpatterns = [
        url(r'^snippets/$', views.SnippetList.as_view()),
        url(r'^snippets/(?P<pk>[0-9]+)/$', csrf_exempt(views.SnippetDetail.as_view())),
    

    ]

    views.py

    from django.views.decorators.csrf import csrf_exempt
    from rest_framework.views import APIView
    class SnippetList(APIView):
        @csrf_exempt
        @need_post_parameters([PARAM_MESSAGE_OBJ])
        def post(self, request, *args, **kwargs):
            data = request.POST.get(PARAM_MESSAGE_OBJ)
    
            try:
                message_obj = json.loads(data)
            except Exception as e:
                return HttpResponseBadRequest(error_json("Could not parse JSON"))
    

    http://www.chenxm.cc/post/509.html

    【讨论】:

      猜你喜欢
      • 2013-05-06
      • 1970-01-01
      • 2013-05-12
      • 1970-01-01
      • 2021-11-27
      • 2017-12-06
      • 2013-10-25
      • 2012-03-17
      • 1970-01-01
      相关资源
      最近更新 更多