Django: учетные данные аутентификации не были предоставлены - PullRequest
0 голосов
/ 27 декабря 2018

Я вытащил дюжину подобных SO-сообщений на эту тему и реализовал их решения настолько, насколько я их понял, но они мне не помогли. Почему я получаю эту ошибку detail: "Authentication credentials were not provided." после использования запроса на исправление AJAX для достижения моей конечной точки Django Rest Framework? Я ценю вашу помощь!

Некоторые детали

  • В шапке написано "Код статуса: 401 не авторизован"
  • Я на моем сервере разработки localHost (Postgres)
  • Я не получаю эту ошибку с любыми другими формами django или запросами ajax (Get and Posts), работающими в других приложениях в этом приложении.
  • Это первый раз, когда я пытаюсь выполнить запрос PATCH
  • В конечном счете, как только этот запрос Ajax Patch сработает, я просто хочу добавить bookid в поле ManyToManyField books в модели api.BookGroup
  • Я пытался следовать рекомендациям в подобных постах, в которых рекомендуется настроить settings.py, чтобы разрешить правильные методы аутентификации и разрешения.
  • ссылаясь на документацию DRF , я также изменил классы разрешений на permission_classes = (IsAuthenticated,), которые должны разрешать запрос исправления, если я вошел в систему при выполнении запроса (и да,Я определенно вошел в систему)
  • Данные формы в заголовке ajax показывают, что я правильно передаю токен CSRF и соответствующие переменные:

    csrfmiddlewaretoken: UjGnVfQTfcmkZKtWjI0m89zlAJqR0wMmUVdh1T1JaiCdyRe2TiW3LPWt
    bookid: 1
    bookgroupid: 71
    

AJAX

function AddToBookGroup(bookgroupid,bookid){
 $.ajax({
    type: "PATCH",
    url: '/api/bookgroups/'+bookgroupid+'/',
    data: {
        csrfmiddlewaretoken: window.CSRF_TOKEN,
        bookid: bookid,
        bookgroupid: bookgroupid
        }, 
    success: function(data){
        console.log( 'success, server says '+data);  
    }
 });
}

URLS.py

from django.urls import path, include
from django.conf.urls import url
from . import views
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('', include(router.urls)),
    url(r'bookgroups/\d+/$', views.BookGroupUpdateSet.as_view()),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

VIEWS.py

from rest_framework.generics import ListAPIView, DestroyAPIView, UpdateAPIView, RetrieveAPIView
from rest_framework.authentication import TokenAuthentication, SessionAuthentication, BasicAuthentication
from rest_framework.authtoken.serializers import AuthTokenSerializer
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.permissions import IsAuthenticatedOrReadOnly, IsAuthenticated
from . import serializers, models, permissions

class BookGroupUpdateSet(UpdateAPIView):
    queryset = models.BookGroup.objects.all()
    model = models.BookGroup
    serializer_class = serializers.BookGroupUpdateSerializer

    def patch(self, request, pk=None):
        permission_classes = (IsAuthenticated,)
        authentication_classes = (TokenAuthentication,)
        bookid = request.Patch['bookid']
        bookgroupid = request.Patch['bookgroupid']
        print("...Print stuff...")

SETTINGS.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'authenticate',
    'api',
    'rest_framework',
    'rest_framework.authtoken',
]

AUTH_USER_MODEL = "api.UserProfile"

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
   'rest_framework.authentication.TokenAuthentication',
   'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
    # 'rest_framework.permissions.AllowAny',  # I've tried this too, same results
    'rest_framework.permissions.IsAuthenticated',
)
}

Ответы [ 2 ]

0 голосов
/ 28 декабря 2018

С Django Rest Framework представлениями вы не используете токены CSRF, а вместо этого пользовательские DRF (это то, для чего rest_framework.authtoken).Когда вы создаете нового пользователя, вы должны создать его токен, например:

def create(self, validated_data):
    from rest_framework.authtoken.models import Token

    try:
        user = models.User.objects.get(email=validated_data.get('email'))
    except User.DoesNotExist:
        user = models.User.objects.create(**validated_data)

        user.set_password(user.password)
        user.save()
        Token.objects.create(user=user) # -------> Token creation

        return user
    else:
        raise CustomValidation('eMail already in use', 'email', status_code=status.HTTP_409_CONFLICT)

Затем вы должны получить токен для пользователя и отправить его в заголовок с именем ключа Authorizationи значение Token <token>.

0 голосов
/ 28 декабря 2018

Как только ваш API View требует аутентификации для доступа, вам необходимо предоставить заголовку запроса заголовок авторизации: Authorization: Token <token>

Итак, как вы получаете этот токен?Согласно документации DRF, вам необходимо создать токен для каждого пользователя в вашей базе данных.Таким образом, вы должны делать это вручную, когда создается новый пользователь, или вы можете использовать виды аутентификации DRF Token, импортировав и используя:

from rest_framework.authtoken.views import ObtainAuthToken

Но я предлагаю вам использовать django-rest-auth app, упрощает процесс аутентификации токена в DRF.https://django -rest-auth.readthedocs.io / ен / последний /

...