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

120

Я разрабатываю 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,)

Сериализатор:

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."}
5
  • 7
    Попробуй это: curl -H "Authorization: Token 12383dcb52d627eabd39e7e88501e96a2sadc55" http://127.0.0.1:8000/api/orders/
    cor
    13 нояб.
  • 1
    Та же ошибка. Учетные данные не были предоставлены 13 ноя '14 в 10:35
  • В моем случае это произошло из-за того, что товарищ по команде переключил пользователя в неактивный режим.
    Brock
    11 дек.
  • Попробуйте сначала прочитать Аутентификацию .
    endless
    26 фев в 12:50
  • @endless Вопрос был 3 года назад. Уже решено 26 фев '18 в 14:32
187

Если вы используете Django на Apache с помощью mod_wsgi, вам необходимо добавить

WSGIPassAuthorization On

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

6
  • 1
    Если вам интересно, где это написать, перейдите по ссылке. stackoverflow.com/questions/49340534/… 18 апр '18 в 8:41
  • 3
    для убунту вроде нет httpd.conf. так что вы должны добавить WSGIPassAuthorization Onв/etc/apache2/apache2.conf 25 июн.
  • Меня смутила проблема, когда мои запросы от почтальона работали с моего локального хоста, но не отправлялись на рабочий сервер. Ваш комментарий решил мою проблему. 10 сен '19 в 14:30
  • Решена Моя проблема, я смог получить данные через api на моем локальном хосте, но при развертывании на сервере через https: // он давал мне такую ​​же ошибку. 4 фев '20 в 11:42
  • Это верно только для производства или также для локальной разработки? 10 мая '20 в 5:15
116

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

REST_FRAMEWORK = {
   'DEFAULT_AUTHENTICATION_CLASSES': (
       'rest_framework.authentication.TokenAuthentication',
   ),
   'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAdminUser'
   ),
}
3
  • Думал , что я сделал это, но я добавил 'rest_framework.authentication.TokenAuthentication'к DEFAULT_PERMISSION_CLASSESвместоDEFAULT_AUTHENTICATION_CLASSES 08 авг.
  • 6
    Спасибо за это решение! Однако я не понимаю, почему я не получил сообщение «Не предоставлены учетные данные для аутентификации». Ошибка при выполнении запроса с Почтальон, в то время как я сделал получаю ошибку , когда мой клиент сделал Угловая запросы. Оба с одним и тем же токеном в заголовке авторизации ... 7 марта '18 в 12:20
  • SessionAuthentication включен по умолчанию и работает со стандартными сеансовыми cookie-файлами, поэтому вполне вероятно, что ваше приложение Angular (или другой JS-фреймворк) работало из-за аутентификации сеанса по умолчанию. 02 июля '20 в 22: 572020-07-02 22:57
37

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

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
    'PAGE_SIZE': 10
}
3
  • 5
    Это SessionAuthenticationбыло то, что исправило это для меня 6 апр '18 в 23:42
  • Исправил и у меня. Интересно, почему в учебнике Django об этом не упоминается. См. Django-rest-framework.org/tutorial/quickstart .
    Nick T
    17 мая '20 в 7:42
  • 1
    Кто-нибудь понял, почему он так себя ведет? сеанс на мобильном устройстве не имеет ничего общего с наличием токена jwt в заголовке запроса !! Я удивлен этим решением после 5 часов копания.
    decoder
    26 февраля в 4:00
18

Просто для других людей , посадок здесь с тем же ошибкой, эта проблема может возникнуть , если ваше 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"
2
  • Как можно печатать request.user? Похоже, что метод POST представления на основе классов никогда не обрабатывается. Где еще можно попробовать распечатать пользователя? 10 мая '20 в 05:19
  • пользователь должен быть аутентифицирован, чтобы иметь возможность быть установленным в объекте запроса. В противном случае он просто печатает анонимного пользователя. Как вы аутентифицируете своего пользователя? 10 мая '20 в 21:14
15

Если вы играете в командной строке (используя 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)

1
  • BasicAuthentication - это не простая проверка подлинности из командной строки 13 мая в 13:07
10

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

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',
   )
}
8

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

Authorization: JWT asdflkj2ewmnsasdfmnwelfkjsdfghdfghdv.wlsfdkwefojdfgh

2
  • То же самое. Использование Next.JS с Django DRF в качестве бэкэнда.
    kenneho
    23 сен '20 в 13:09
  • Согласовано. Впервые попробовал django с реакцией, и ваш ответ мне помог.
    Rahul
    24 ноя '20 в 11:50
5

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

2
  • В моем случае я не установил флажок ... :) Спасибо, это дало мне подсказку 21 сен '20 в 14:19
  • Я использую thunder client (расширение для кода VS), чтобы проверить свой API. Флажок автоматически устанавливается, когда мы добавляем новый заголовок поля или что-то еще. Так что это никогда не приходило мне в голову. Но, увидев этот ответ, я снял флажок, а затем снова проверил, и это сработало. Спасибо.. 20 июня в 9:32
4

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

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

Попробуй, у меня это сработало.

В settings.py

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

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

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

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

2
  • 1
    Извините, но на этот вопрос уже дан более подробный ответ, чем на ваш ... 12 марта '20 в 6: 142020-03-12 06:14
  • Это для людей, которым нужно быстрое решение 12 марта '20 в 9:06
1

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

2
  • какие классы аутентификации?
    Sam
    4 дек '20 в 14:24
  • как нам это сделать? 13 июня в 16:37
0

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

0

если кто-то пришел сюда из Full Stack React & Django [5] - Django Token Authentication - Traversy Media Итак, вам нужно что-то вроде этого

аккаунты / 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