Как я могу заставить django-rest-framework-jwt возвращать токен при регистрации?

У меня есть базовая служба отдыха django, которая

  1. регистрирует человека и
  2. обновляет свой пароль.

Я хочу добавить поверх него аутентификацию jwt. Если я буду следовать руководству, мне нужно будет добавить новый URL-адрес с именем «api-token-auth» в urls.py проекта. Но я не хочу добавлять этот новый URL и хочу, чтобы мой вызов регистрации отправлял токен в ответ.

Вот мой код:

serializers.py

class UserSerializer(serializers.HyperlinkedModelSerializer):
    def create(self, validated_data):
        user = User(
            username=validated_data['username']
        )
        user.set_password(validated_data['password'])
        user.save()
        return user

    def update(self, instance, validated_data):
        instance.set_password(validated_data['password'])
        instance.save()
        return instance

    class Meta:
        model = User
        fields = ('url', 'username', 'password')
        lookup_field = 'username'
        write_only_fields = ('password',)

views.py

class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.exclude(is_superuser=1)
    serializer_class = UserSerializer
    lookup_field = 'username'
  1. Что нужно сделать для этого? должен ли я вызывать api-auth-token внутри метода создания моего сериализатора?
  2. Как django-rest-framework-jwt обрабатывает несколько токенов аутентификации и правильно определяет, какой токен принадлежит какому пользователю? Особенно, если он не хранит токены в БД.
  3. Как я могу использовать этот механизм аутентификации, чтобы ограничить моего пользователя просмотром / обновлением / удалением только его пользователя?
  4. Как я могу использовать этот механизм аутентификации для чего-либо в целом. Например, если пользователь хочет записать свое имя в /tmp/abcd.txt. Как я могу убедиться, что это смогут сделать только аутентифицированные пользователи?
  5. Есть ли в этом подходе потенциальные лазейки? Должен ли я использовать тот же код, если мое приложение будет хранить много секретных данных?

person diwakarb    schedule 30.06.2015    source источник


Ответы (2)


Вопрос 1. Для создания токенов вручную при регистрации вы можете определить и использовать следующий метод:

import jwt
from rest_framework_jwt.utils import jwt_payload_handler

def create_token(user):
    payload = jwt_payload_handler(user)
    token = jwt.encode(payload, settings.SECRET_KEY)
    return token.decode('unicode_escape')

вы можете добавить этот метод в представление и сгенерировать токен после регистрации пользователя и вернуть его в ответе.

Вопрос 2: токены JWT не нужно хранить в базе данных. Вы можете узнать больше о том, как работает JWT, на http://jwt.io/.

Вопросы 3 и 4. Чтобы использовать токены для ограничения доступа к определенному представлению, особенно APIView или одному из его подклассов, или представлению, предоставленному платформой Django Rest, вам необходимо указать классы разрешений. Например:

from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

class ExampleView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request, format=None):
        content = {
            'status': 'request was permitted'
        }
        return Response(content)

Вопрос 5. Одна потенциальная лазейка при работе с Django Rest Framework - это разрешения по умолчанию, которые вы устанавливаете в настройках вашего приложения; если, например, вы AllowAny в настройках, это сделает все представления общедоступными, если вы специально не переопределите классы разрешений в каждом представлении.

person James Muranga    schedule 30.06.2015

В принятом ответе есть код, который генерирует токен, но не показывает, как его интегрировать в сериализатор / просмотр. Также не уверен, что руководство jwt.encode - это хороший современный способ сделать это, если у нас уже есть jwt_encode_handler для этого. Вы можете создать SerializerMethodField и создать там токены:

token = serializers.SerializerMethodField()

def get_token(self, obj):
    jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
    jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

    payload = jwt_payload_handler(obj)
    token = jwt_encode_handler(payload)
    return token

Затем добавьте поле token к Meta.fields.

Рабочий пример

person Ivan Borshchov    schedule 02.04.2017