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를 비활성화 할 수 있습니까?
답변
이 오류가 발생하는 이유는 무엇입니까?
이것은 SessionAuthentication
DRF에서 사용 하는 기본 체계 때문에 발생 합니다. 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는 SessionAuthentication
AUTHENTICATION 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 Authentication
REST_AUTHENTICATION_CLASSES에서 제거하면 모든 csrf 기반 문제가 자동으로 제거됩니다. 그러나이 경우 Browseable api가 작동하지 않을 수 있습니다.
게다가이 오류는 세션 인증에서도 오지 않아야합니다. API에 TokenAuthentication과 같은 사용자 지정 인증을 사용해야 하며 인증 토큰과 함께 요청에 Accept:application/json
및 Content-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 ...():