Django Rest Framework - Thông tin xác thực không được cung cấp


106

Tôi đang phát triển một API bằng Django Rest Framework. Tôi đang cố gắng liệt kê hoặc tạo một đối tượng "Đặt hàng", nhưng khi tôi cố truy cập bảng điều khiển, tôi gặp lỗi này:

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

Lượt xem:

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

Bộ nối tiếp:

class OrderSerializer(serializers.HyperlinkedModelSerializer):

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

Và các URL của tôi:

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

Và sau đó tôi đang sử dụng lệnh này trong bảng điều khiển:

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

Và lỗi nói:

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

5
Hãy thử điều này:curl -H "Authorization: Token 12383dcb52d627eabd39e7e88501e96a2sadc55" http://127.0.0.1:8000/api/orders/
cor

1
Cùng một lỗi. Thông tin xác thực không được cung cấp
Marcos Aguayo

Trong trường hợp của tôi, điều này đã xảy ra do một đồng đội chuyển người dùng sang chế độ không hoạt động.
Brock

Cố gắng đọc Xác thực trước.
vô tận

@endless Câu hỏi là 3 năm trước. Nó đã được giải quyết
Marcos Aguayo

Câu trả lời:


167

Nếu bạn đang runnig Django trên Apache bằng mod_wsgi, bạn phải thêm

WSGIPassAuthorization On

trong httpd.conf của bạn. Nếu không, tiêu đề ủy quyền sẽ bị mod_wsgi loại bỏ.


1
Trong trường hợp nếu bạn đang tự hỏi nơi để viết điều này, hãy theo liên kết. stackoverflow.com/questions/49340534/…
user2858738

2
đối với ubuntu có vẻ như không httpd.conf. vì vậy bạn phải thêm WSGIPassAuthorization Onvào/etc/apache2/apache2.conf
suhailvs

Tôi đã bối rối bởi một sự cố trong đó các yêu cầu của tôi từ Postman đang hoạt động từ máy chủ cục bộ của tôi nhưng không hoạt động khi được gửi đến máy chủ trực tiếp. Bình luận của bạn đã giải quyết được vấn đề của tôi.
RommelTJ

Đã giải quyết Sự cố của tôi, tôi có thể lấy dữ liệu qua api trên máy chủ cục bộ của mình, nhưng khi được triển khai trên máy chủ qua https: // nó lại gây cho tôi một lỗi tương tự.
Mir Suhail

Điều này chỉ đúng trong sản xuất hay cho phát triển địa phương?
MadPhysicist

99

Giải quyết bằng cách thêm "DEFAULT_AUTHENTICATION_CLASSES" vào settings.py

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

Tôi nghĩ rằng tôi đã làm điều này, nhưng tôi đã thêm 'rest_framework.authentication.TokenAuthentication'vào DEFAULT_PERMISSION_CLASSESthay vìDEFAULT_AUTHENTICATION_CLASSES
netigger

4
Cảm ơn cho giải pháp này! Tuy nhiên, tôi không hiểu tại sao tôi không nhận được thông báo "Thông tin xác thực không được cung cấp". khi thực hiện yêu cầu với Postman, trong khi tôi đã gặp lỗi khi ứng dụng Angular của tôi đưa ra yêu cầu. Cả hai với dấu hiệu tương tự trong tiêu đề ủy quyền ...
Sander Vanden Hautte

SessionAuthenticationđược bật theo mặc định và hoạt động với cookie phiên tiêu chuẩn, vì vậy có khả năng ứng dụng Angular (hoặc khuôn khổ JS khác) của bạn đang hoạt động do xác thực phiên mặc định.
Kevin Brown

29

Điều này giúp tôi không có "DEFAULT_PERMISSION_CLASSES" trong settings.py

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

3
Đó SessionAuthenticationlà những gì đã sửa nó cho tôi
Caleb_Allen

Đã sửa nó cho tôi quá. Tự hỏi tại sao hướng dẫn Django về điều này không đề cập đến nó. Xem django-rest-framework.org/tutorial/quickstart .
Nick T

15

Chỉ dành riêng cho những người khác hạ cánh lên đây với cùng một lỗi, vấn đề này có thể xảy ra nếu bạn request.userAnonymousUservà không phải là người sử dụng đúng người thực sự có thẩm quyền để truy cập vào địa chỉ URL. Bạn có thể thấy điều đó bằng cách in giá trị của request.user. Nếu đó thực sự là một người dùng ẩn danh, các bước sau có thể giúp:

  1. Hãy chắc chắn rằng bạn có 'rest_framework.authtoken'trong INSTALLED_APPStrong của bạn settings.py.

  2. Hãy chắc chắn rằng bạn có cái này ở đâu đó trong settings.py:

    REST_FRAMEWORK = {
    
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.TokenAuthentication',
            # ...
        ),
    
        # ...
    }
    
  3. Đảm bảo rằng bạn có mã thông báo chính xác cho người dùng đã đăng nhập. Nếu bạn không có mã thông báo, hãy tìm hiểu cách lấy tại đây . Về cơ bản, bạn cần thực hiện POSTyêu cầu một chế độ xem cung cấp cho bạn mã thông báo nếu bạn cung cấp tên người dùng và mật khẩu chính xác. Thí dụ:

    curl -X POST -d "user=Pepe&password=aaaa"  http://localhost:8000/
    
  4. Đảm bảo chế độ xem mà bạn đang cố gắng truy cập có những điều sau:

    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. Sử dụng curlngay bây giờ theo cách này:

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

Thí dụ:

    curl -X GET http://127.0.0.1:8001/expenses/  -H "Authorization: Token 9463b437afdd3f34b8ec66acda4b192a815a15a8"

Làm thế nào một người có thể in request.user? Có vẻ như phương thức POST của một dạng xem dựa trên lớp sẽ không bao giờ được xử lý. Tôi có thể thử in người dùng ở đâu khác?
MadPhysicist

người dùng phải được xác thực để có thể được thiết lập trong đối tượng yêu cầu. Nếu không, nó chỉ in người dùng ẩn danh. Bạn xác thực người dùng của mình như thế nào?
sherelock

11

Nếu bạn đang chơi xung quanh dòng lệnh (sử dụng curl hoặc HTTPie, v.v.), bạn có thể sử dụng BasicAuthentication để kiểm tra / sử dụng API của bạn

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

Sau đó bạn có thể sử dụng lọn tóc

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

hoặc httpie (dễ nhìn hơn):

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

hoặc cái gì đó khác như Advanced Rest Client (ARC)


9

Tôi cũng phải đối mặt với điều tương tự vì tôi đã bỏ lỡ thêm

verify_classes = (TokenAuthentication)

trong lớp xem API của tôi.

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

Ngoài những điều trên, chúng tôi cần nói rõ ràng với Django về Xác thực trong tệp settings.py.

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

3

Thêm SessionAuthentication trong settings.py sẽ thực hiện công việc

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


3

Đối với tôi, tôi phải thêm tiêu đề Ủy quyền của mình bằng "JWT" ​​thay vì "Bearer" hoặc "Token" trên Django DRF. Sau đó, nó bắt đầu hoạt động. ví dụ -

Authorization: JWT asdflkj2ewmnsasdfmnwelfkjsdfghdfghdv.wlsfdkwefojdfgh


Ở đây cũng vậy. Sử dụng Next.JS với Django DRF làm phụ trợ.
kenneho

2

Tôi đang gặp sự cố này với người đưa thư. Thêm điều này vào tiêu đề ... nhập mô tả hình ảnh ở đây


Trong trường hợp của tôi, tôi đã không chọn hộp kiểm ... :) Cảm ơn, điều này đã cho tôi manh mối
Laxmikant

1

Vì nó là phiên Đăng nhập nên bạn cần cung cấp cho bạn thông tin đăng nhập để 127.0.0:8000/admin quản trị viên và đăng nhập sau nó sẽ hoạt động tốt


1
Xin lỗi, nhưng câu hỏi này đã được trả lời chi tiết hơn câu hỏi của bạn ...
Muhammad Dyas Yaskur

Điều này dành cho những người cần giải pháp nhanh
Aishwarya kabadi

1

Có lẽ điều này có thể hoạt động

Trong settings.py

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

Thêm cái này nữa

REST_FRAMEWORK = {
    ....
    ...
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    )
    ...
    ..
}

0

Nếu bạn đang sử dụng authentication_classesthì bạn phải có is_activenhư Truetrong Usermô hình, có thể là Falsetheo mặc định.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.