Wiem, że istnieją odpowiedzi dotyczące Django Rest Framework, ale nie mogłem znaleźć rozwiązania mojego problemu.
Mam aplikację, która ma uwierzytelnianie i pewne funkcje. Dodałem do niego nową aplikację, która korzysta z Django Rest Framework. Chcę korzystać z biblioteki tylko w tej aplikacji. Chcę również wysłać żądanie POST i zawsze otrzymuję tę odpowiedź:
{
"detail": "CSRF Failed: CSRF token missing or incorrect."
}
Mam następujący kod:
# 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})
Chcę dodać API bez wpływu na bieżącą aplikację. Więc moje pytanie brzmi: jak mogę wyłączyć CSRF tylko dla tej aplikacji?
django
django-rest-framework
csrf
django-csrf
Irene Texas
źródło
źródło
Odpowiedzi:
Dlaczego ten błąd się dzieje?
Dzieje się tak z powodu domyślnego
SessionAuthentication
schematu używanego przez DRF. DRFSessionAuthentication
używa struktury sesji Django do uwierzytelniania, która wymaga sprawdzenia CSRF.Jeśli nie zdefiniujesz żadnej
authentication_classes
w swoim widoku / zestawie widoków, DRF używa tych klas uwierzytelniania jako domyślnych.Ponieważ DRF musi obsługiwać zarówno uwierzytelnianie sesyjne, jak i nieesesyjne w tych samych widokach, wymusza sprawdzanie CSRF tylko dla uwierzytelnionych użytkowników. Oznacza to, że tylko uwierzytelnione żądania wymagają tokenów CSRF, a żądania anonimowe mogą być wysyłane bez tokenów CSRF.
Jeśli używasz interfejsu API w stylu AJAX z SessionAuthentication, musisz dołączyć prawidłowy token CSRF dla wszystkich „niebezpiecznych” wywołań metod HTTP, takich jak
PUT, PATCH, POST or DELETE
żądania.Co wtedy zrobić?
Teraz, aby wyłączyć sprawdzanie csrf, możesz utworzyć niestandardową klasę uwierzytelniania,
CsrfExemptSessionAuthentication
która wykracza pozaSessionAuthentication
klasę domyślną . W tej klasie uwierzytelniania nadpisujemyenforce_csrf()
sprawdzanie, które miało miejsce w plikuSessionAuthentication
.Twoim zdaniem możesz zdefiniować
authentication_classes
jako:To powinno obsłużyć błąd csrf.
źródło
Łatwiejsze rozwiązanie:
W views.py użyj nawiasów klamrowych CsrfExemptMixin i authentication_classes:
źródło
Zmodyfikuj urls.py
Jeśli zarządzasz swoimi trasami w urls.py, możesz opakować żądane trasy za pomocą csrf_exempt (), aby wykluczyć je z oprogramowania pośredniczącego weryfikacji CSRF.
Alternatywnie, jako dekorator Niektórzy mogą uznać użycie dekoratora @csrf_exempt za bardziej odpowiednie dla ich potrzeb
na przykład,
powinien dostać pracę wykonaną!
źródło
Dla wszystkich, którzy nie znaleźli pomocnej odpowiedzi. Tak DRF automatycznie usuwa ochronę CSRF, jeśli nie używasz
SessionAuthentication
KLASY UWIERZYTELNIANIA, na przykład wielu programistów używa tylko JWT:Ale problem
CSRF not set
może wystąpić z innego powodu, na przykład nieprawidłowo dodana ścieżka do widoku:zamiast
źródło
Wypróbowałem kilka powyższych odpowiedzi i uznałem, że utworzenie oddzielnej klasy było trochę przesadą.
Dla porównania napotkałem ten problem, próbując zaktualizować metodę widoku opartą na funkcjach do metody widoku opartej na klasach w celu rejestracji użytkownika.
Korzystając z widoków opartych na klasach (CBV) i Django Rest Framework (DRF), dziedzicz z klasy ApiView i ustaw klasy Permissions_classes i authentication_classes na pustą krotkę. Znajdź przykład poniżej.
źródło
Jeśli nie chcesz używać uwierzytelniania opartego na sesji, możesz usunąć
Session Authentication
z REST_AUTHENTICATION_CLASSES, co spowoduje automatyczne usunięcie wszystkich problemów opartych na csrf. Ale w takim przypadku Browseable API może nie działać.Poza tym ten błąd nie powinien występować nawet przy uwierzytelnianiu sesji. Powinieneś używać niestandardowego uwierzytelniania, takiego jak TokenAuthentication dla swojego interfejsu API i upewnij się, że wysyłasz
Accept:application/json
iContent-Type:application/json
(pod warunkiem, że używasz json) w swoich żądaniach wraz z tokenem uwierzytelniania.źródło
Musisz to dodać, aby zapobiec domyślnemu uwierzytelnianiu sesji: (settings.py)
Następnie: (views.py)
źródło
Uderza mnie ten sam problem. Postępowałem zgodnie z tym odniesieniem i zadziałało. Rozwiązaniem jest stworzenie oprogramowania pośredniego
Dodaj plik disable.py w jednej ze swoich aplikacji (w moim przypadku jest to „myapp”)
I dodaj oprogramowanie pośrednie do MIDDLEWARE_CLASSES
źródło
Jeśli używasz wyłącznego środowiska wirtualnego dla swojej aplikacji, możesz zastosować następujące podejście bez efektywnych innych aplikacji.
To, co zaobserwowałeś, dzieje się, ponieważ
rest_framework/authentication.py
ma ten kod wauthenticate
metodzieSessionAuthentication
class:Możesz zmodyfikować
Request
klasę tak, aby miała wywoływaną właściwośćcsrf_exempt
i zainicjować ją wewnątrz odpowiedniej klasy View,True
jeśli nie chcesz sprawdzać CSRF. Na przykład:Następnie zmodyfikuj powyższy kod w następujący sposób:
Jest kilka powiązanych zmian, które musisz zrobić w
Request
klasie. Pełna implementacja jest dostępna tutaj (z pełnym opisem): https://github.com/piaxis/django-rest-framework/commit/1bdb872bac5345202e2f58728d0e7fad70dfd7edźródło
Moje rozwiązanie jest pokazane jak cios. Po prostu udekoruj moją klasę.
źródło
Podczas korzystania z REST API POST brak nagłówka żądania X-CSRFToken może powodować ten błąd. Dokumentacja Django zawiera przykładowy kod dotyczący pobierania i ustawiania wartości tokenu CSRF z JS.
Jak wskazano w odpowiedziach powyżej, sprawdzenie CSRF ma miejsce, gdy używana jest SessionAuthentication. Innym podejściem jest użycie TokenAuthentication, ale pamiętaj, że należy go umieścić na pierwszym miejscu na liście DEFAULT_AUTHENTICATION_CLASSES w ustawieniu REST_FRAMEWORK.
źródło
Może to również stanowić problem podczas ataku DNS Rebinding .
Może to również mieć znaczenie między zmianami DNS. Oczekiwanie na pełne opróżnienie DNS rozwiąże ten problem, jeśli działał przed problemami / zmianami DNS.
źródło