Django Rest Framework - nie podano danych uwierzytelniających

106

Rozwijam API przy użyciu Django Rest Framework. Próbuję wyświetlić lub utworzyć obiekt „Zamówienie”, ale kiedy próbuję uzyskać dostęp do konsoli, pojawia się następujący błąd:

{"detail": "Authentication credentials were not provided."}

Wyświetlenia:

from django.shortcuts import render
from rest_framework import viewsets
from django.contrib.auth.models import User
from rest_framework.renderers import JSONRenderer, YAMLRenderer
from rest_framework.response import Response
from rest_framework.views import APIView
from order.models import *
from API.serializers import *
from rest_framework.permissions import IsAuthenticated

class OrderViewSet(viewsets.ModelViewSet):
    model = Order
    serializer_class = OrderSerializer
    permission_classes = (IsAuthenticated,)

Serializator:

class OrderSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = Order
        fields = ('field1', 'field2')

I moje adresy URL:

# -*- coding: utf-8 -*-
from django.conf.urls import patterns, include, url
from django.conf import settings
from django.contrib import admin
from django.utils.functional import curry
from django.views.defaults import *
from rest_framework import routers
from API.views import *

admin.autodiscover()

handler500 = "web.views.server_error"
handler404 = "web.views.page_not_found_error"

router = routers.DefaultRouter()
router.register(r'orders', OrdersViewSet)

urlpatterns = patterns('',
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    url(r'^api-token-auth/', 'rest_framework.authtoken.views.obtain_auth_token'),
    url(r'^api/', include(router.urls)),
)

A potem używam tego polecenia w konsoli:

curl -X GET http://127.0.0.1:8000/api/orders/ -H 'Authorization: Token 12383dcb52d627eabd39e7e88501e96a2sadc55'

A błąd mówi:

{"detail": "Authentication credentials were not provided."}
Marcos Aguayo
źródło
5
Spróbuj tego:curl -H "Authorization: Token 12383dcb52d627eabd39e7e88501e96a2sadc55" http://127.0.0.1:8000/api/orders/
cor
1
Ten sam błąd. Nie podano danych uwierzytelniających
Marcos Aguayo
W moim przypadku stało się to z powodu przełączenia użytkownika przez członka drużyny w tryb nieaktywny.
Brock
Spróbuj najpierw przeczytać Uwierzytelnianie .
niekończący się
@endless Pytanie było 3 lata temu. To już rozwiązane
Marcos Aguayo

Odpowiedzi:

168

Jeśli używasz Django na Apache używając mod_wsgi, musisz dodać

WSGIPassAuthorization On

w twoim httpd.conf. W przeciwnym razie nagłówek autoryzacji zostanie usunięty przez mod_wsgi.

Robert Kovac
źródło
1
Jeśli zastanawiasz się, gdzie to napisać, kliknij link. stackoverflow.com/questions/49340534/…
user2858738
2
dla ubuntu wydaje się, że nie httpd.conf. więc trzeba dodać WSGIPassAuthorization Onw/etc/apache2/apache2.conf
suhailvs
Byłem zdezorientowany problemem polegającym na tym, że moje żądania z Postmana działały z mojego lokalnego hosta, ale nie były wysyłane na serwer aktywny. Twój komentarz rozwiązał mój problem.
RommelTJ
Rozwiązany Mój problem, byłem w stanie uzyskać dane przez interfejs API na moim hoście lokalnym, ale po wdrożeniu na serwerze przez https: // dawał mi ten sam błąd.
Mir Suhail
Czy dotyczy to tylko produkcji, czy też rozwoju lokalnego?
MadPhysicist
100

Rozwiązane przez dodanie „DEFAULT_AUTHENTICATION_CLASSES” do mojego settings.py

REST_FRAMEWORK = {
   'DEFAULT_AUTHENTICATION_CLASSES': (
       'rest_framework.authentication.TokenAuthentication',
   ),
   'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAdminUser'
   ),
}
Marcos Aguayo
źródło
Myśl Zrobiłem to, ale ja dodaje 'rest_framework.authentication.TokenAuthentication'się DEFAULT_PERMISSION_CLASSESzamiastDEFAULT_AUTHENTICATION_CLASSES
netigger
4
Dzięki za to rozwiązanie! Nie rozumiem jednak, dlaczego nie otrzymałem komunikatu „Nie podano danych uwierzytelniających”. Błąd podczas wykonywania żądania z Postman, natomiast ja nie pojawia się błąd, gdy mój klient kątowa wykonana żądań. Oba z tym samym tokenem w nagłówku Authorization ...
Sander Vanden Hautte
SessionAuthenticationjest domyślnie włączona i działa ze standardowymi plikami cookie sesji, więc prawdopodobnie Twoja aplikacja Angular (lub inna platforma JS) działała z powodu domyślnego uwierzytelniania sesji.
Kevin Brown
29

Pomoże mi to bez „DEFAULT_PERMISSION_CLASSES” w moim settings.py

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
    'PAGE_SIZE': 10
}
uestcfei
źródło
3
To SessionAuthenticationwłaśnie rozwiązało problem
Caleb_Allen,
Naprawiłem to też dla mnie. Ciekawe, dlaczego samouczek Django o tym nie wspomina o tym. Zobacz django-rest-framework.org/tutorial/quickstart .
Nick T
15

Tylko dla innych ludzi lądowania tutaj z tego samego błędu, to problem może pojawić się jeśli request.userjest AnonymousUser, a nie właściwą użytkownika, który jest faktycznie uprawniony do dostępu do adresu URL. Możesz to zobaczyć, drukując wartość request.user. Jeśli rzeczywiście jest to użytkownik anonimowy, poniższe kroki mogą pomóc:

  1. Upewnij się, że 'rest_framework.authtoken'w INSTALLED_APPSna swój settings.py.

  2. Upewnij się, że masz to gdzieś w settings.py:

    REST_FRAMEWORK = {
    
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.TokenAuthentication',
            # ...
        ),
    
        # ...
    }
    
  3. Upewnij się, że masz prawidłowy token dla zalogowanego użytkownika. Jeśli nie masz tokena, dowiedz się, jak go uzyskać tutaj . Zasadniczo musisz wysłać POSTżądanie do widoku, który daje token, jeśli podasz poprawną nazwę użytkownika i hasło. Przykład:

    curl -X POST -d "user=Pepe&password=aaaa"  http://localhost:8000/
    
  4. Upewnij się, że widok, do którego próbujesz uzyskać dostęp, zawiera:

    class some_fancy_example_view(ModelViewSet): 
    """
    not compulsary it has to be 'ModelViewSet' this can be anything like APIview etc, depending on your requirements.
    """
        permission_classes = (IsAuthenticated,) 
        authentication_classes = (TokenAuthentication,) 
        # ...
    
  5. Użyj curlteraz w ten sposób:

    curl -X (your_request_method) -H  "Authorization: Token <your_token>" <your_url>
    

Przykład:

    curl -X GET http://127.0.0.1:8001/expenses/  -H "Authorization: Token 9463b437afdd3f34b8ec66acda4b192a815a15a8"
sherelock
źródło
Jak można drukować request.user? Wygląda na to, że metoda POST widoku opartego na klasach nigdy nie jest przetwarzana. Gdzie jeszcze mogę spróbować wydrukować użytkownika?
MadPhysicist
użytkownik musi być uwierzytelniony, aby mógł zostać ustawiony w obiekcie żądania. W przeciwnym razie po prostu drukuje anonimowego użytkownika. Jak uwierzytelniasz swojego użytkownika?
sherelock
12

Jeśli bawisz się w wierszu poleceń (używając curl lub HTTPie itp.), Możesz użyć BasicAuthentication do przetestowania / użytkownika swojego API

    REST_FRAMEWORK = {
        'DEFAULT_PERMISSION_CLASSES': [
            'rest_framework.permissions.IsAuthenticated',
        ],
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.BasicAuthentication',  # enables simple command line authentication
            'rest_framework.authentication.SessionAuthentication',
            'rest_framework.authentication.TokenAuthentication',
        )
    }

Następnie możesz użyć curl

curl --user user:password -X POST http://example.com/path/ --data "some_field=some data"

lub httpie (łatwiejsze dla oczu):

http -a user:password POST http://example.com/path/ some_field="some data"

lub coś innego, jak Advanced Rest Client (ARC)

Lukeaus
źródło
9

Ja też stanąłem w obliczu tego samego, odkąd przegapiłem dodawanie

authentication_classes = (TokenAuthentication)

w mojej klasie widoku interfejsu API.

class ServiceList(generics.ListCreateAPIView):
    authentication_classes = (SessionAuthentication, BasicAuthentication, TokenAuthentication)
    queryset = Service.objects.all()
    serializer_class = ServiceSerializer
    permission_classes = (IsAdminOrReadOnly,)

Oprócz powyższego, musimy wyraźnie poinformować Django o uwierzytelnianiu w pliku settings.py.

REST_FRAMEWORK = {
   'DEFAULT_AUTHENTICATION_CLASSES': (
   'rest_framework.authentication.TokenAuthentication',
   )
}
prashant
źródło
3

Dodanie SessionAuthentication w settings.py wykona zadanie

REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', ), }

Pritam Roy
źródło
3

W moim przypadku musiałem dołączyć do mojego nagłówka Authorization „JWT” zamiast „Bearer” lub „Token” na Django DRF. Potem zaczęło działać. np. -

Authorization: JWT asdflkj2ewmnsasdfmnwelfkjsdfghdfghdv.wlsfdkwefojdfgh

kiko carisse
źródło
To samo tutaj. Używanie Next.JS z Django DRF jako zapleczem.
kenneho
2

Miałem problem z listonoszem Dodaj to do nagłówków ... wprowadź opis obrazu tutaj

mikelus
źródło
W moim przypadku nie zaznaczyłem checkboxa ... :) Dzięki, to dało mi wskazówkę
Laxmikant
1

Ponieważ jest to logowanie sesyjne, musisz podać poświadczenia, więc 127.0.0:8000/admin zaloguj się jako administrator i zaloguj się później, będzie działać dobrze

Aishwarya kabadi
źródło
1
Przepraszamy, ale na to pytanie udzielono już bardziej szczegółowych odpowiedzi niż twoje ...
Muhammad Dyas Yaskur
To jest dla ludzi, którzy potrzebują szybkiego rozwiązania
Aishwarya kabadi
1

Prawdopodobnie to zadziała

W settings.py

SIMPLE_JWT = {
     ....
     ...
     # Use JWT 
     'AUTH_HEADER_TYPES': ('JWT',),
     # 'AUTH_HEADER_TYPES': ('Bearer',),
     ....
     ...
}

Dodaj to też

REST_FRAMEWORK = {
    ....
    ...
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    )
    ...
    ..
}
Harshit Gangwar
źródło
0

Jeśli używasz authentication_classes, powinieneś mieć is_activejak Truew Usermodelu, który może być Falsedomyślnie.

Piyush Jaiswal
źródło