Django Rest Framework - учетные данные для аутентификации не предоставлены

Я разрабатываю API с использованием Django Rest Framework. Я пытаюсь перечислить или создать объект "Порядок", но когда я пытаюсь получить доступ к консоли, выдает мне эту ошибку:

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

Просмотры:

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,)

Serializer:

class OrderSerializer(serializers.HyperlinkedModelSerializer):

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

И мои 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)),
)

И тогда я использую эту команду в консоли:

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

И об ошибке говорят:

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

20 ответов

Решение

Решено добавлением "DEFAULT_AUTHENTICATION_CLASSES" в мои settings.py

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

Если вы запускаете Django на Apache, используя mod_wsgi, вы должны добавить

WSGIPassAuthorization On

в вашем httpd.conf. В противном случае заголовок авторизации будет удален mod_wsgi.

Это поможет мне без "DEFAULT_PERMISSION_CLASSES" в моих settings.py

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

Просто для других людей, приземляющихся здесь с той же ошибкой, эта проблема может возникнуть, если ваш request.user является AnonymousUser и не тот пользователь, который действительно авторизован для доступа к URL. Вы можете увидеть это, напечатав значение request.user, Если это действительно анонимный пользователь, эти шаги могут помочь:

  1. Убедитесь, что у вас есть 'rest_framework.authtoken' в INSTALLED_APPS в вашем settings.py,

  2. Убедитесь, что у вас есть это где-то в settings.py:

    REST_FRAMEWORK = {
    
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.TokenAuthentication',
            # ...
        ),
    
        # ...
    }
    
  3. Убедитесь, что у вас есть правильный токен для пользователя, который вошел в систему. Если у вас нет токена, узнайте, как его получить, здесь. В основном вам нужно сделать POST запрос на просмотр, который дает вам токен, если вы предоставите правильное имя пользователя и пароль. Пример:

    curl -X POST -d "user=Pepe&password=aaaa"  http://localhost:8000/
    
  4. Убедитесь, что представление, к которому вы пытаетесь получить доступ, имеет следующее:

    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. использование curl теперь так:

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

Пример:

    curl -X GET http://127.0.0.1:8001/expenses/  -H "Authorization: Token 9463b437afdd3f34b8ec66acda4b192a815a15a8"

Если вы играете в командной строке (используя curl, HTTPie и т. Д.), Вы можете использовать BasicAuthentication для тестирования / использования вашего 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',
        )
    }

Затем вы можете использовать curl

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

или httpie (это легче для глаз):

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

или что-то еще, как Advanced Rest Client (ARC)

Мне пришлось добавить к заголовку авторизации "JWT" вместо "Bearer" или "Token" в Django DRF. Потом заработало. например -

Authorization: JWT asdflkj2ewmnsasdfmnwelfkjsdfghdfghdv.wlsfdkwefojdfgh

У меня была такая проблема с почтальоном. Добавьте это в заголовки...

Я тоже сталкивался с тем же, так как я пропустил добавление

authentication_classes = (TokenAuthentication)

в моем классе просмотра API.

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

В дополнение к вышесказанному, нам нужно явно сообщить Django об аутентификации в файле settings.py.

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

Наверное, это могло сработать

В settings.py

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

Добавьте это тоже

REST_FRAMEWORK = {
    ....
    ...
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    )
    ...
    ..
}

Добавление SessionAuthentication в settings.py сделает работу

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

if anyone come here from Full Stack React &amp;amp; Django [5] - Django Token Authentication - Traversy Media So you need to something like this

accounts/api.py

      from rest_framework import generics, permissions
from rest_framework.response import Response
from knox.models import AuthToken
from .serializers import LoginSerializer, RegisterSerializer, UserSerializer
from knox.auth import TokenAuthentication

# Register Api


class RegisterAPI(generics.GenericAPIView):
    serializer_class = RegisterSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.save()
        return Response({
            "user": UserSerializer(user, context=self.get_serializer_context()).data,
            "token": AuthToken.objects.create(user)[1]
        })

# Login Api


class LoginAPI(generics.GenericAPIView):
    serializer_class = LoginSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data
        return Response({
            "user": UserSerializer(user, context=self.get_serializer_context()).data,
            "token": AuthToken.objects.create(user)[1]
        })

# Get User Api


class UserAPI(generics.RetrieveAPIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = [
        permissions.IsAuthenticated,
    ]

    serializer_class = UserSerializer

    def get_object(self):
        return self.request.user

В моем случае TokenAuthentication отсутствовал

      @authentication_classes([SessionAuthentication, BasicAuthentication])

Я изменил его на ниже, и это сработало

      @authentication_classes([SessionAuthentication, BasicAuthentication, TokenAuthentication])

Также убедитесь, что токен авторизации / ключ API действительно действителен. В Сообщение об ошибке похоже на то, что возвращает API, если ключ также недействителен (я столкнулся с этим, когда случайно использовал неправильный ключ API).

Поскольку это сеанс входа, вам необходимо предоставить учетные данные, поэтому 127.0.0:8000/adminadmin и войдите позже, он будет работать нормально

Если вы используете authentication_classes тогда у тебя должно быть is_active как True в User модель, которая может быть False по умолчанию.

Я добавил это в settings.py:

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

}

и я создал суперпользователя и создал токен, используя:

      python manage.py createsuperuser

и создал токен, используяhttp://127.0.0.1:8000/admin/authtoken/tokenproxy/и ничего больше, и это просто работало.

Если вы используете CDN, убедитесь, что CDN не удаляет заголовок запроса при пересылке запроса на ваш сервер.

У меня была такая же проблема с почтальоном и бэкэндом Django. Я использовалBearer tokenно это начало давать сбой, мне пришлось вручную добавитьAuthorizationЗаголовок включенHeadersпредваряя егоTokenт.е.Token token

У меня была странная проблема с этой ошибкой.

Я правильно получал токен, правильно передал токен авторизации в Postman и все еще получал эту ошибку.

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

Я искал это в Интернете и проверил много вопросов SO. Но ничего не помогло.

Затем я закрыл приложение Postman и перезапустил его, и все заработало. Я понятия не имел, почему Почтальон так себя вел.

К счастью, проблема решена :)

Я бы также добавил это для тех, кто хочет реализовать аутентификацию только по токену. Убедитесь, что ваш набор представлений имеет атрибут «authentication_classes».

Например:

      from rest_framework.authentication import TokenAuthentication

class TaskViewSet(viewsets.ModelViewSet):
     """
     Tasks for the current user. This endpoint allows tasks to be viewed or edited. 
     """
     queryset = Task.objects.all().order_by('-created_at')
     serializer_class = TaskSerializer
     authentication_classes = [TokenAuthentication]
     permission_classes = [permissions.IsAuthenticated]

Это позволит обойти требование о том, чтобы имя пользователя и пароль пользователя запрашивались в запросе сеанса.

Другие вопросы по тегам