Django Rest Framework: no se proporcionaron las credenciales de autenticación

106

Estoy desarrollando una API usando Django Rest Framework. Estoy tratando de listar o crear un objeto "Pedido", pero cuando intento acceder a la consola, aparece este error:

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

Puntos de vista:

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

Serializador:

class OrderSerializer(serializers.HyperlinkedModelSerializer):

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

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

Y luego estoy usando este comando en la consola:

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

Y el error dice:

{"detail": "Authentication credentials were not provided."}
Marcos Aguayo
fuente
5
Prueba esto:curl -H "Authorization: Token 12383dcb52d627eabd39e7e88501e96a2sadc55" http://127.0.0.1:8000/api/orders/
cor
1
Mismo error. No se proporcionaron credenciales de autenticación
Marcos Aguayo
En mi caso, esto sucedió debido a que un compañero de equipo cambió al usuario al modo inactivo.
Brock
Intente leer Autenticación primero.
interminable
@endless La pregunta fue hace 3 años. Ya está resuelto
Marcos Aguayo

Respuestas:

168

Si está ejecutando Django en Apache usando mod_wsgi, debe agregar

WSGIPassAuthorization On

en su httpd.conf. De lo contrario, mod_wsgi eliminará el encabezado de autorización.

Robert Kovac
fuente
1
En caso de que se esté preguntando dónde escribir esto, siga el enlace. stackoverflow.com/questions/49340534/…
user2858738
2
para ubuntu parece que no httpd.conf. así que hay que añadir WSGIPassAuthorization Onen/etc/apache2/apache2.conf
suhailvs
Estaba confundido por un problema en el que mis solicitudes de Postman funcionaban desde mi host local pero no cuando se enviaban al servidor en vivo. Tu comentario resolvió mi problema.
RommelTJ
Resuelto mi problema, pude obtener datos a través de api en mi localhost, pero cuando se implementó en el servidor a través de https: // me estaba dando el mismo error.
Mir Suhail
¿Es esto cierto solo en la producción o también para el desarrollo local?
MadPhysicist
100

Resuelto agregando "DEFAULT_AUTHENTICATION_CLASSES" a mi configuración.py

REST_FRAMEWORK = {
   'DEFAULT_AUTHENTICATION_CLASSES': (
       'rest_framework.authentication.TokenAuthentication',
   ),
   'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAdminUser'
   ),
}
Marcos Aguayo
fuente
Pensé que hice esto, pero había agregado 'rest_framework.authentication.TokenAuthentication'en DEFAULT_PERMISSION_CLASSESlugar deDEFAULT_AUTHENTICATION_CLASSES
netigger
4
¡Gracias por esta solución! Sin embargo, no entiendo por qué no obtuve el mensaje "No se proporcionaron las credenciales de autenticación". error al realizar la consulta con cartero, mientras que yo hice obtener el error cuando mi cliente angular hizo peticiones. Ambos con el mismo token en el encabezado de Autorización ...
Sander Vanden Hautte
SessionAuthenticationestá habilitado de forma predeterminada y funciona con las cookies de sesión estándar, por lo que es probable que su aplicación Angular (u otro marco JS) estuviera funcionando debido a la autenticación de sesión predeterminada.
Kevin Brown
29

Esto me ayuda sin "DEFAULT_PERMISSION_CLASSES" en mi configuración.py

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
    'PAGE_SIZE': 10
}
uestcfei
fuente
3
El SessionAuthenticationera lo fija para mí
Caleb_Allen
Lo arreglé para mí también. Me pregunto por qué el tutorial de Django sobre esto no lo menciona. Consulte django-rest-framework.org/tutorial/quickstart .
Nick T
15

Solo para otras personas que llegan aquí con el mismo error, este problema puede surgir si usted request.useres AnonymousUsery no el usuario correcto que está realmente autorizado para acceder a la URL. Puede verlo imprimiendo el valor de request.user. Si de hecho es un usuario anónimo, estos pasos pueden ayudar:

  1. Asegúrate de que tienes 'rest_framework.authtoken'en INSTALLED_APPSen tu settings.py.

  2. Asegúrate de tener esto en algún lugar settings.py:

    REST_FRAMEWORK = {
    
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.TokenAuthentication',
            # ...
        ),
    
        # ...
    }
    
  3. Asegúrese de tener el token correcto para el usuario que inició sesión. Si no tiene el token, obtenga información sobre cómo obtenerlo aquí . Básicamente, debe realizar una POSTsolicitud a una vista que le proporciona el token si proporciona el nombre de usuario y la contraseña correctos. Ejemplo:

    curl -X POST -d "user=Pepe&password=aaaa"  http://localhost:8000/
    
  4. Asegúrese de que la vista a la que está intentando acceder tenga estos:

    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. Úselo curlahora de esta manera:

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

Ejemplo:

    curl -X GET http://127.0.0.1:8001/expenses/  -H "Authorization: Token 9463b437afdd3f34b8ec66acda4b192a815a15a8"
sherelock
fuente
¿Cómo se puede imprimir request.user? Parece que el método POST de una vista basada en clases nunca se procesa. ¿Dónde más puedo intentar imprimir el usuario?
MadPhysicist
el usuario debe estar autenticado para poder establecerse en el objeto de solicitud. De lo contrario, solo imprime usuario anónimo. ¿Cómo autentica a su usuario?
sherelock
12

Si está jugando en la línea de comandos (usando curl, HTTPie, etc.) puede usar BasicAuthentication para probar / usar su 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',
        )
    }

Luego puedes usar curl

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

o httpie (es más fácil para los ojos):

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

o algo más como Advanced Rest Client (ARC)

lukeaus
fuente
9

Yo también enfrenté lo mismo desde que me perdí de agregar

authentication_classes = (TokenAuthentication)

en mi clase de vista API.

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

Además de lo anterior, debemos informar explícitamente a Django sobre la autenticación en el archivo settings.py.

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

Agregar SessionAuthentication en settings.py hará el trabajo

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

Pritam Roy
fuente
3

Para mí, tuve que anteponer mi encabezado de autorización con "JWT" ​​en lugar de "Bearer" o "Token" en Django DRF. Entonces empezó a funcionar. p.ej -

Authorization: JWT asdflkj2ewmnsasdfmnwelfkjsdfghdfghdv.wlsfdkwefojdfgh

kiko carisse
fuente
Igual que aquí. Usando Next.JS con Django DRF como backend.
Kenneho
2

Estaba teniendo este problema con el cartero. Agregue esto a los encabezados ... ingrese la descripción de la imagen aquí

mikelus
fuente
En mi caso, no había seleccionado la casilla de verificación ... :) Gracias, esto me dio la pista
Laxmikant
1

Dado que es el inicio de sesión de sesión, debe proporcionarle las credenciales, así que haga el 127.0.0:8000/admin administrador e inicie sesión más tarde, funcionará bien

Aishwarya kabadi
fuente
1
Lo siento, pero esta pregunta ya está respondida con más detalles que la suya ...
Muhammad Dyas Yaskur
Esto es para las personas que necesitan una solución rápida
Aishwarya kabadi
1

Probablemente esto podría funcionar

En settings.py

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

Agrega esto también

REST_FRAMEWORK = {
    ....
    ...
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    )
    ...
    ..
}
Harshit Gangwar
fuente
0

Si está utilizando authentication_classes, entonces debería haber is_activecomo Trueen el Usermodelo, que podría ser Falsepor defecto.

Piyush Jaiswal
fuente