Django возвращает «Учетные данные для аутентификации не были предоставлены» при попытке аутентификации с помощью токена
(я пробовал решения в похожих вопросах, но они мне не подошли).
Я создаю простое веб-приложение на основе Django REST, в котором пользователь будет регистрироваться, создавать некоторые события, позже входить в систему и просматривать события.
Вот вид события:
class EventGetCreate(APIView):
authentication_classes = (TokenAuthentication,)
permission_classes = (IsAuthenticated,)
def get(self, request):
created_user = request.user
events = Event.objects.filter(creator=created_user)
serializer = EventSummary(events, many=True)
return Response(serializer.data)
Его файл urls.py выглядит следующим образом:
from django.urls import path, include
from . import views
app_name = 'event'
urlpatterns = [
...
path('eventviewall/', views.EventGetCreate.as_view()),
]
В файле core/urls.py для получения токена используется следующее:
from .views import UserViewSet
from rest_framework.authtoken.views import ObtainAuthToken, obtain_auth_token
app_name = 'core'
router = routers.DefaultRouter()
router.register('users', UserViewSet)
urlpatterns = [
path('auth/', obtain_auth_token),
path('register/', include(router.urls)),
]
Используя postman, я могу успешно войти в систему и получить токен: Отправьте запрос на http://127.0.0.1:8000/api/auth/ и получите следующее (пример токена):
{
"token": "xxyyzz"
}
Теперь я хочу отправить этот токен в запросе get и просмотреть события, созданные пользователем. Я отправляю запрос на http://127.0.0.1:8000/event/eventviewall/, с указанным выше токеном, установленным на вкладке Authorization -> Bearer token.
Однако я получаю следующий ответ:
{
"detail": "Authentication credentials were not provided."
}
Теперь, если я установлю permission_classes = () в представлении выше (как было предложено в некоторых ответах на похожие вопросы), я получу следующую ошибку:
TypeError at /event/eventviewall/
Field 'id' expected a number but got <django.contrib.auth.models.AnonymousUser object at 0x0000018BEF4573A0>.
Я получаю, что эта ошибка возникает из-за того, что Django устанавливает для request.user значение AnonymousUser, так как не может аутентифицировать пользователя.
Как это исправить?
Проблема в том, что это не Bearer Token.
Вы должны предоставить свой собственный заголовок Authorization
со значением Token: <token>
.
Такие приложения, как Postman, не имеют встроенного заголовка авторизации такого типа, поэтому вам нужно добавить его вручную.
Проблема заключается в разборе заголовка auth (вы используете неожиданное значение заголовка Bearer
). Исправление заключается в том, чтобы либо изменить значение заголовка, либо изменить ожидаемое значение (оба варианта возможны).
Подробности непосредственно с сайта https://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication:
Для аутентификации клиентов ключ токена должен быть включен в HTTP-заголовок авторизации. Ключ должен иметь префикс в виде строки литерал «Token», с пробелами, разделяющими эти две строки. Для например:
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
Если вы хотите использовать другое ключевое слово в заголовке, например
Bearer
, просто создайте подклассTokenAuthentication
и установите переменную классаkeyword
. переменную.