Django Rest Framework - credenciais de autenticação não foram fornecidas

98

Estou desenvolvendo uma API usando Django Rest Framework. Estou tentando listar ou criar um objeto "Pedido", mas quando tento acessar o console, vejo este erro:

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

Visualizações:

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

E meus URLs:

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

E então estou usando este comando no console:

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

E o erro diz:

{"detail": "Authentication credentials were not provided."}
Marcos Aguayo
fonte
5
Experimente:curl -H "Authorization: Token 12383dcb52d627eabd39e7e88501e96a2sadc55" http://127.0.0.1:8000/api/orders/
cor
1
Mesmo erro. Credenciais de autenticação não fornecidas
Marcos Aguayo
No meu caso, isso aconteceu devido a um colega de equipe mudar o usuário para o modo inativo.
Brock
Tente ler a autenticação primeiro.
infinito em
@endless A questão foi há 3 anos. Já está resolvido
Marcos Aguayo

Respostas:

159

Se você está executando o Django no Apache usando mod_wsgi, você deve adicionar

WSGIPassAuthorization On

em seu httpd.conf. Caso contrário, o cabeçalho de autorização será removido por mod_wsgi.

Robert Kovac
fonte
1
Caso você esteja se perguntando onde escrever isso, siga o link. stackoverflow.com/questions/49340534/…
user2858738
1
para o Ubuntu parece que não httpd.conf. então você tem que adicionar WSGIPassAuthorization Onem/etc/apache2/apache2.conf
suhailvs
Fiquei confuso com um problema em que minhas solicitações do Postman estavam funcionando no meu host local, mas não quando enviadas para o servidor ativo. Seu comentário resolveu meu problema.
RommelTJ de
Resolvido meu problema, consegui obter dados via api em meu localhost, mas quando implantado no servidor via https: // estava dando o mesmo erro.
Mir Suhail
Isso é válido apenas para a produção ou também para o desenvolvimento local?
MadPhysicist
93

Resolvido ao adicionar "DEFAULT_AUTHENTICATION_CLASSES" às minhas configurações.py

REST_FRAMEWORK = {
   'DEFAULT_AUTHENTICATION_CLASSES': (
       'rest_framework.authentication.TokenAuthentication',
   ),
   'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAdminUser'
   ),
}
Marcos Aguayo
fonte
Pensei que tivesse feito isso, mas adicionei 'rest_framework.authentication.TokenAuthentication'ao em DEFAULT_PERMISSION_CLASSESvez deDEFAULT_AUTHENTICATION_CLASSES
netigger
4
Obrigado por esta solução! Não entendo, no entanto, por que não recebi a mensagem "Credenciais de autenticação não fornecidas". erro ao fazer a solicitação com o Postman, ao passo que recebi o erro quando meu cliente Angular fez solicitações. Ambos com o mesmo token no cabeçalho de autorização ...
Sander Vanden Hautte
SessionAuthenticationestá habilitado por padrão e funciona com os cookies de sessão padrão, portanto, é provável que seu aplicativo Angular (ou outra estrutura JS) estivesse funcionando por causa da autenticação de sessão padrão.
Kevin Brown
27

Isso me ajuda sem "DEFAULT_PERMISSION_CLASSES" em minhas configurações.py

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
    'PAGE_SIZE': 10
}
uestcfei
fonte
3
O SessionAuthenticationfoi o que fixa-lo para mim
Caleb_Allen
Consertou para mim também. Gostaria de saber por que o tutorial do Django sobre isso não menciona isso. Veja django-rest-framework.org/tutorial/quickstart .
Nick T
15

Apenas para outras pessoas que chegam aqui com o mesmo erro, esse problema pode surgir se você request.userfor AnonymousUsere não o usuário correto que está realmente autorizado a acessar o URL. Você pode ver isso imprimindo o valor de request.user. Se for realmente um usuário anônimo, estas etapas podem ajudar:

  1. Certifique-se de que você tem 'rest_framework.authtoken'na INSTALLED_APPSsua settings.py.

  2. Certifique-se de ter isso em algum lugar em settings.py:

    REST_FRAMEWORK = {
    
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.TokenAuthentication',
            # ...
        ),
    
        # ...
    }
  3. Certifique-se de ter o token correto para o usuário que está conectado. Se você não tiver o token, saiba como obtê-lo aqui . Basicamente, você precisa fazer uma POSTsolicitação para uma visualização que fornece o token se você fornecer o nome de usuário e a senha corretos. Exemplo:

    curl -X POST -d "user=Pepe&password=aaaa"  http://localhost:8000/
  4. Certifique-se de que a vista da propriedade que você está tentando acessar tenha estes:

    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. Use curlagora desta forma:

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

Exemplo:

    curl -X GET http://127.0.0.1:8001/expenses/  -H "Authorization: Token 9463b437afdd3f34b8ec66acda4b192a815a15a8"
sherelock
fonte
Como se pode imprimir request.user? Parece que o método POST de uma visão baseada em classe nunca está sendo processado. Onde mais posso tentar imprimir o usuário?
MadPhysicist
o usuário deve ser autenticado para poder ser definido no objeto de solicitação. Caso contrário, ele apenas imprime usuário anônimo. Como você está autenticando seu usuário?
sherelock
11

Se você estiver brincando na linha de comando (usando curl ou HTTPie etc), você pode usar BasicAuthentication para testar / usar sua 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',
        )
    }

Você pode então usar curl

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

ou httpie (é mais fácil para os olhos):

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

ou algo como Cliente de Repouso Avançado (ARC)

Lukeaus
fonte
8

Eu também enfrentei o mesmo desde que deixei de adicionar

authentication_classes = (TokenAuthentication)

na minha classe de visualização da API.

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

Além do acima, precisamos informar explicitamente ao Django sobre a autenticação no arquivo settings.py.

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

Adicionar SessionAuthentication em settings.py fará o trabalho

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

Pritam Roy
fonte
1

Como é o login da sessão, você precisa fornecer as credenciais, então faça o 127.0.0:8000/admin administrador e faça o login mais tarde, ele funcionará bem

Aishwarya Kabadi
fonte
1
Desculpe, mas esta pergunta já foi respondida com mais detalhes do que a sua ...
Muhammad Dyas Yaskur
Isso é para pessoas que precisam de uma solução rápida
Aishwarya kabadi
1

Para mim, tive que preceder meu cabeçalho de autorização com "JWT" ​​em vez de "Bearer" ou "Token" no Django DRF. Então começou a funcionar. por exemplo -

Authorization: JWT asdflkj2ewmnsasdfmnwelfkjsdfghdfghdv.wlsfdkwefojdfgh

kiko carisse
fonte
0

Se você estiver usando authentication_classes, então você deve ter is_activecomo Trueno Usermodelo, que pode ser Falsepor padrão.

Piyush Jaiswal
fonte