Проблема с аутентификацией JWT в django-rest-framework - PullRequest
0 голосов
/ 07 марта 2019

У меня проблема с аутентификацией JWT с использованием django-rest-knox.

Ошибка: Detail: Authentication credentials were not provided.

ENDPOINT: /api/auth/login/

Заголовки в запросе POST к конечной точке: { Content-Type: application/json }

тело:

{
    "username": "admin",
    "password": 1234
}

Вид входа в API:

class UserLoginAPIView(generics.GenericAPIView):
    serializer_class = UserLoginSerializer

    def post(self, request, *args, **kwargs):
        data = request.data
        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data
        token = AuthToken.objects.create(user)
        return Response({
            "user": UserSerializer(user,
                                   context=self.get_serializer_context()).data,
            "token": token
        })

Serializer:

class UserLoginSerializer(serializers.Serializer):
    username = serializers.CharField()
    password = serializers.CharField()


    def validate(self, data):
        user = authenticate(**data)
        if user and user.is_active:
            return user
        raise serializers.ValidationError("Invalid Credentials")

Настройки по умолчанию:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'knox.auth.TokenAuthentication',
    ]
}

Ответы [ 2 ]

0 голосов
/ 07 марта 2019

Я думаю, что ваша процедура неправильная.Согласно документам Knox, Вам необходимо дать разрешение на вход в систему конечной точке.Но вы не дали разрешение на доступ к конечной точке входа в систему.Таким образом, ваша конечная точка входа в систему выглядит следующим образом:

# views.py 
from django.contrib.auth import login
from rest_framework import permissions
from rest_framework.authtoken.serializers import AuthTokenSerializer
from knox.views import LoginView as KnoxLoginView

class LoginView(KnoxLoginView):
    permission_classes = (permissions.AllowAny,)

    def post(self, request, format=None):
        serializer = AuthTokenSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        login(request, user)
        return super(LoginView, self).post(request, format=None)

# settings.py 
REST_KNOX = {
  'USER_SERIALIZER': 'knox.serializers.UserSerializer',
}

Если вы используете сериализатор пользователя в настройках, вы получите токен с именем запрашивающего пользователя, например, ниже

{"user":{"username":"admin"},"token":"00bd2a5e517800b75a8f36bbf3baea4c839169108b25a5a5ea599a4ecda974c0"}

Подробнее здесь, Нокс

0 голосов
/ 07 марта 2019

Привет, кажется, вы используете knox, который не совсем то же самое, но по сути он похож. Возможно, ваш взгляд защищен из-за ваших настроек DEFAULT_PERMISSION_CLASSES.

Если вы хотите войти через это представление, вам нужно установить

permission_classes = [AllowAny, ]

на ваш взгляд.

Однако я бы не стал этого делать, поскольку это взлом. (Я знаю, что прошел через это, и мы написали одну и ту же статью).

Правильный способ сделать это - определить сериализатор пользователя в файле конфигурации / настроек Django, чтобы вы могли получить необходимую информацию при входе в систему.

REST_KNOX = {
    'USER_SERIALIZER': 'auth.serializers.UserRetrieveSerializer'
}

Затем просто расширьте представление входа по умолчанию и используйте basic auth в качестве класса аутентификации.

from knox.views import LoginView as KnoxLoginView
from rest_framework.authentication import BasicAuthentication
from rest_framework.permissions import IsAuthenticated

class LoginAPI(KnoxLoginView):
    """
    Login endpoint.
    """
    authentication_classes = [BasicAuthentication, ]
    permission_classes = [IsAuthenticated, ]

И для всех остальных видов вы можете использовать knox.auth.TokenAuthentication. И это все ...

Соответствующий код для тестирования это:

import base64

def get_basic_auth_header(username, password):
    return 'Basic %s' % base64.b64encode(
        ('%s:%s' % (username, password)).encode('ascii')).decode()

 from rest_framework.test import APITestCase

 class MyTestCase(APITestCase):
     username = 'foo'
     password = 'bar'

     def test_login(self):
         # Add basic auth credentials
         self.client.credentials(
             HTTP_AUTHORIZATION=get_basic_auth_header(
                 self.username, self.password))
         etc...

В вашем urls.py

from knox import views as knox_views
from .views import LoginAPI

...
    url(r'^login/$', LoginAPI.as_view(), name='knox_login'),                    
    url(r'^logout/$', knox_views.LogoutView.as_view(), name='knox_logout'),     
    url(r'^logoutall/$', knox_views.LogoutAllView.as_view(), name='knox_logoutall'),
...


...