Django Rest Framework-未提供身份验证凭据


98

我正在使用Django Rest Framework开发API。我试图列出或创建“订单”对象,但是当我尝试访问控制台时,出现此错误:

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

我的网址:

# -*- 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
试试这个:curl -H "Authorization: Token 12383dcb52d627eabd39e7e88501e96a2sadc55" http://127.0.0.1:8000/api/orders/
cor 2014年

1
同样的错误。未提供身份验证凭据
Marcos Aguayo 2014年

就我而言,这是由于队友将用户切换到非活动模式而发生的。
布罗克

尝试先阅读身份验证
无尽

@endless问题是3年前。它已经解决了
Marcos Aguayo

Answers:


159

如果您使用mod_wsgi在Apache上运行Django,则必须添加

WSGIPassAuthorization On

在您的httpd.conf中。否则,授权标头将被mod_wsgi剥离。


1
如果您想知道在哪里写,请点击链接。stackoverflow.com/questions/49340534/...
user2858738

1
对于ubuntu似乎没有httpd.conf。所以你要添加WSGIPassAuthorization On/etc/apache2/apache2.conf
suhailvs

我对Postman的请求正在本地主机上正常工作但发送到实时服务器时无法正常工作的问题感到困惑。您的评论解决了我的问题。
RommelTJ

解决了我的问题,我能够通过localhost上的api获取数据,但是当通过https://部署在服务器上时,它却给了我同样的错误。
Mir Suhail

这仅在生产或本地开发中适用吗?
MadPhysicist

93

通过在我的settings.py中添加“ DEFAULT_AUTHENTICATION_CLASSES”来解决

REST_FRAMEWORK = {
   'DEFAULT_AUTHENTICATION_CLASSES': (
       'rest_framework.authentication.TokenAuthentication',
   ),
   'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAdminUser'
   ),
}

以为我这样做了,但是我添加'rest_framework.authentication.TokenAuthentication'DEFAULT_PERMISSION_CLASSES代替DEFAULT_AUTHENTICATION_CLASSES
netigger

4
感谢您的解决方案!但是,我不明白为什么我没有得到“未提供身份验证凭据”的信息。使用Postman发出请求时出现错误,而当Angular客户端发出请求时我确实收到了错误。两者在授权标头中使用相同的令牌...
Sander Vanden Hautte

SessionAuthentication默认情况下处于启用状态,并且可以与标准会话cookie一起使用,因此由于默认的会话身份验证,您的Angular(或其他JS框架)应用程序可能正在运行。
凯文·布朗

27

这可以帮助我在settings.py中没有“ DEFAULT_PERMISSION_CLASSES”的情况

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

3
SessionAuthentication就是为我解决的问题
Caleb_Allen '18

也为我修复了它。想知道为什么关于Django的教程没有提到它。参见django-rest-framework.org/tutorial/quickstart
尼克T

15

仅对于其他人,由于同样的错误而以同样的错误登陆,如果您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"

如何打印request.user?似乎永远不会处理基于类的视图的POST方法。我还能在哪里尝试打印用户?
MadPhysicist

用户必须经过身份验证才能在请求对象中设置。否则,它将仅打印匿名用户。您如何验证用户?
夏洛克

11

如果您在命令行中玩耍(使用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)的东西


8

我也遇到了同样的事情,因为我错过了添加

authentication_classes =(令牌认证)

在我的API视图类中。

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

除了上述内容外,我们还需要在settings.py文件中明确告知Django 身份验证

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

2

在settings.py中添加SessionAuthentication就可以了

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



1

对我来说,我必须在Django DRF上的Authorization标头前面加上“ JWT”,而不是“ Bearer”或“ Token”。然后它开始工作。例如-

Authorization: JWT asdflkj2ewmnsasdfmnwelfkjsdfghdfghdv.wlsfdkwefojdfgh


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.