[django] Django Rest Framework는 csrf를 제거합니다.

Django Rest Framework에 대한 답변이 있다는 것을 알고 있지만 내 문제에 대한 해결책을 찾을 수 없습니다.

인증 및 일부 기능이있는 응용 프로그램이 있습니다. Django Rest Framework를 사용하는 새 앱을 추가했습니다. 이 앱에서만 라이브러리를 사용하고 싶습니다. 또한 POST 요청을하고 싶습니다. 항상이 응답을받습니다.

{
    "detail": "CSRF Failed: CSRF token missing or incorrect."
}

다음 코드가 있습니다.

# urls.py
from django.conf.urls import patterns, url


urlpatterns = patterns(
    'api.views',
    url(r'^object/$', views.Object.as_view()),
)

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from django.views.decorators.csrf import csrf_exempt


class Object(APIView):

    @csrf_exempt
    def post(self, request, format=None):
        return Response({'received data': request.data})

현재 애플리케이션에 영향을주지 않고 API를 추가하고 싶습니다. 그래서 내 질문은 어떻게이 앱에 대해서만 CSRF를 비활성화 할 수 있습니까?



답변

이 오류가 발생하는 이유는 무엇입니까?

이것은 SessionAuthenticationDRF에서 사용 하는 기본 체계 때문에 발생 합니다. DRF SessionAuthentication는 CSRF를 확인해야하는 인증을 위해 Django의 세션 프레임 워크를 사용합니다.

authentication_classes뷰 / 뷰셋에 아무것도 정의하지 않으면 DRF는이 인증 클래스를 기본값으로 사용합니다.

'DEFAULT_AUTHENTICATION_CLASSES'= (
    'rest_framework.authentication.SessionAuthentication',
    'rest_framework.authentication.BasicAuthentication'
),

DRF는 동일한 뷰에 대한 세션 및 비 세션 기반 인증을 모두 지원해야하므로 인증 된 사용자에 대해서만 CSRF 검사를 시행합니다. 이는 인증 된 요청에만 CSRF 토큰이 필요하며 익명 요청은 CSRF 토큰없이 전송 될 수 있음을 의미합니다.

SessionAuthentication과 함께 AJAX 스타일 API를 사용하는 경우 PUT, PATCH, POST or DELETE요청 과 같은 “안전하지 않은”HTTP 메서드 호출에 대해 유효한 CSRF 토큰을 포함해야 합니다.

그러면 무엇을해야합니까?

이제 csrf 검사를 비활성화 CsrfExemptSessionAuthentication하려면 기본 SessionAuthentication클래스 에서 확장되는 사용자 지정 인증 클래스 를 만들 수 있습니다 . 이 인증 클래스에서는 enforce_csrf()실제 .NET 내부에서 발생한 검사를 재정의합니다 SessionAuthentication.

from rest_framework.authentication import SessionAuthentication, BasicAuthentication

class CsrfExemptSessionAuthentication(SessionAuthentication):

    def enforce_csrf(self, request):
        return  # To not perform the csrf check previously happening

보기에서 다음과 같이 정의 할 수 authentication_classes있습니다.

authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)

이것은 csrf 오류를 처리해야합니다.


답변

더 쉬운 솔루션 :

views.py에서 중괄호 CsrfExemptMixin 및 authentication_classes를 사용하십시오.

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from django.views.decorators.csrf import csrf_exempt
from braces.views import CsrfExemptMixin


class Object(CsrfExemptMixin, APIView):
    authentication_classes = []

    def post(self, request, format=None):
        return Response({'received data': request.data})


답변

urls.py 수정

urls.py에서 경로를 관리하는 경우 원하는 경로를 csrf_exempt ()로 래핑하여 CSRF 확인 미들웨어에서 제외 할 수 있습니다.

from django.conf.urls import patterns, url
    from django.views.decorators.csrf import csrf_exempt
    import views

urlpatterns = patterns('',
    url(r'^object/$', csrf_exempt(views.ObjectView.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')

작업을 완료해야합니다!


답변

도움이되는 답을 찾지 못한 모든 사람들을 위해. 예 DRF는 SessionAuthenticationAUTHENTICATION CLASS를 사용하지 않는 경우 CSRF 보호를 자동으로 제거합니다. 예 를 들어 많은 개발자가 JWT 만 사용합니다.

'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),

그러나 CSRF not set다른 이유로 인해 문제 가 발생할 수 있습니다. 예를 들어보기에 경로를 올바르게 추가하지 않았기 때문입니다.

url(r'^api/signup/', CreateUserView),  # <= error! DRF cant remove CSRF because it is not as_view that does it!

대신에

url(r'^api/signup/', CreateUserView.as_view()),


답변

위의 답변 중 몇 가지를 시도해 보았고 별도의 수업을 만드는 것이 다소 과도하다고 느꼈습니다.

참고로 사용자 등록을 위해 함수 기반 뷰 메서드를 클래스 기반 뷰 메서드로 업데이트하려고 할 때이 문제가 발생했습니다.

CBV (클래스 기반 뷰) 및 DRF (Django Rest Framework)를 사용하는 경우 ApiView 클래스에서 상속하고 permission_classes 및 authentication_classes를 빈 튜플로 설정합니다. 아래에서 예를 찾으십시오.

class UserRegistrationView(APIView):

    permission_classes = ()
    authentication_classes = ()

    def post(self, request, *args, **kwargs):

        # rest of your code here


답변

세션 기반 인증을 사용하지 않으려는 경우 Session AuthenticationREST_AUTHENTICATION_CLASSES에서 제거하면 모든 csrf 기반 문제가 자동으로 제거됩니다. 그러나이 경우 Browseable api가 작동하지 않을 수 있습니다.

게다가이 오류는 세션 인증에서도 오지 않아야합니다. API에 TokenAuthentication과 같은 사용자 지정 인증을 사용해야 하며 인증 토큰과 함께 요청에 Accept:application/jsonContent-Type:application/json(json을 사용 하는 경우) 전송 해야합니다.


답변

기본 세션 인증을 방지하려면 다음을 추가해야합니다. (settings.py)

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    )
}

그런 다음 : (views.py)

from rest_framework.permissions import AllowAny

class Abc(APIView):
    permission_classes = (AllowAny,)

    def ...():