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를 비활성화 할 수 있습니까?
이 오류가 발생하는 이유는 무엇입니까?
이것은 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')
작업을 완료해야합니다!
If you do not want to use session based authentication, you can remove Session Authentication
from REST_AUTHENTICATION_CLASSES and that would automatically remove all csrf based issues. But in that case Browseable apis might not work.
Besides this error should not come even with session authentication. You should use custom authentication like TokenAuthentication for your apis and make sure to send Accept:application/json
and Content-Type:application/json
(provided you are using json) in your requests along with authentication token.
For all who did not find a helpful answer. Yes DRF automatically removes CSRF protection if you do not use SessionAuthentication
AUTHENTICATION CLASS, for example, many developers use only JWT:
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
But issue CSRF not set
may be occurred from some another reason, for exmple you not correctly added path to you view:
url(r'^api/signup/', CreateUserView), # <= error! DRF cant remove CSRF because it is not as_view that does it!
instead of
url(r'^api/signup/', CreateUserView.as_view()),
I tried a few of the answers above and felt creating a separate class was a little overboard.
For reference, I ran into this problem when trying to update a function based view method to a class based view method for user registration.
When using class-based-views (CBVs) and Django Rest Framework (DRF), Inherit from the ApiView class and set permission_classes and authentication_classes to an empty tuple. Find an example below.
class UserRegistrationView(APIView):
permission_classes = ()
authentication_classes = ()
def post(self, request, *args, **kwargs):
# rest of your code here
I am struck with the same problem. I followed this reference and it worked. Solution is to create a middleware
Add disable.py file in one of your apps (in my case it is 'myapp')
class DisableCSRF(object):
def process_request(self, request):
setattr(request, '_dont_enforce_csrf_checks', True)
And add the middileware to the MIDDLEWARE_CLASSES
MIDDLEWARE_CLASSES = (
myapp.disable.DisableCSRF,
)
If you are using an exclusive virtual environment for your application, you can use the following approach without effective any other applications.
What you observed happens because rest_framework/authentication.py
has this code in the authenticate
method of SessionAuthentication
class:
self.enforce_csrf(request)
You can modify the Request
class to have a property called csrf_exempt
and initialize it inside your respective View class to True
if you do not want CSRF checks. For example:
Next, modify the above code as follows:
if not request.csrf_exempt:
self.enforce_csrf(request)
There are some related changes you'd have to do it in the Request
class. A complete implementation is available here (with full description): https://github.com/piaxis/django-rest-framework/commit/1bdb872bac5345202e2f58728d0e7fad70dfd7ed
My Solution is shown blow. Just decorate my class.
from django.views.decorators.csrf import csrf_exempt
@method_decorator(csrf_exempt, name='dispatch')
@method_decorator(basic_auth_required(
target_test=lambda request: not request.user.is_authenticated
), name='dispatch')
class GenPedigreeView(View):
pass
This could also be a problem during a DNS Rebinding attack.
In between DNS changes, this can also be a factor. Waiting till DNS is fully flushed will resolve this if it was working before DNS problems/changes.
참고URL : https://stackoverflow.com/questions/30871033/django-rest-framework-remove-csrf
'Programming' 카테고리의 다른 글
SQL 연결이 열려 있는지 또는 닫혀 있는지 확인 (0) | 2020.08.27 |
---|---|
문자열이 여러 접두사 중 하나로 시작하는지 확인하는 방법은 무엇입니까? (0) | 2020.08.27 |
Java 가비지 콜렉션 로그 메시지 (0) | 2020.08.27 |
jstl의 foreach 루프에서 인덱스 값을 얻는 방법 (0) | 2020.08.27 |
HTTP는 UDP를 사용합니까? (0) | 2020.08.27 |