Django rest framework аутентификации пользователей

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

Прямо сейчас наши API полностью разрешены. Любой может создавать, получать доступ и удалять что угодно. Мы хотим добавить эти элементы управления доступом.

  • Пользователь должен пройти аутентификацию для доступа к опросу или списку опросов.
  • Только авторизованные пользователи могут создать опрос.
  • Только аутентифицированный пользователь может создать выбор.
  • Прошедшие проверку пользователи могут создавать варианты только для созданных ими опросов.
  • Прошедшие проверку пользователи могут удалять только созданные им опросы.
  • Только авторизованный пользователь может голосовать. Пользователи могут голосовать за чужие опросы.

Чтобы включить контроль доступа, нам нужно добавить еще два API

  • API для создания пользователя, мы будем называть эту конечную точку /users/
  • API для проверки пользователя и получения токена для его идентификации, мы будем называть эту конечную точку /login/

Создание пользователя 
Мы добавим пользовательский сериализатор, который позволит создавать. Добавьте следующий код в serializers.py.

# ...
from django.contrib.auth.models import User

# ...
class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ('username', 'email', 'password')
        extra_kwargs = {'password': {'write_only': True}}

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

Мы переопределили метод ModelSerializer create() для сохранения User экземпляров. Мы гарантируем, что мы правильно установили пароль user.set_password, а не устанавливали необработанный пароль в качестве хеша. Мы также не хотим возвращать пароль в ответ, который мы гарантируем .extra_kwargs = {'password': {'write_only': True}}

Давайте также добавим представления в User Serializer для создания пользователя и подключим его к urls.py

# in apiviews.py
# ...
from .serializers import PollSerializer, ChoiceSerializer, VoteSerializer, UserSerializer

# ...
class UserCreate(generics.CreateAPIView):
    serializer_class = UserSerializer

# in urls.py
# ...
from .apiviews import PollViewSet, ChoiceList, CreateVote, UserCreate


urlpatterns = [
    # ...
    path("users/", UserCreate.as_view(), name="user_create"),
]

Мы можем проверить этот API, отправив сообщение /users/ с этим JSON.

{
    "username": "nate.silver",
    "email": "nate.silver@example.com",
    "password": "FiveThirtyEight"
}

Которые отдают этот ответ.

{
    "username": "nate.silver",
    "email": "nate.silver@example.com"
}

Попробуйте опубликовать тот же JSON, и вы получите ответ об ошибке (код состояния HTTP 400)

{
    "username": [
        "A user with that username already exists."
    ]
}

Настройка схемы аутентификации 
С Django Rest Framework мы можем установить схему аутентификации по умолчанию, которая применяется ко всем видам использования DEFAULT_AUTHENTICATION_CLASSES. Мы будем использовать токен аутентификации в этом руководстве. В вашем settings.py добавьте это.

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

Вам также необходимо включить rest_framework.authtoken приложение, поэтому обновите его INSTALLED_APPS в файле settings.py.

INSTALLED_APPS = (
    ...
    'rest_framework.authtoken'
)

Запустите для создания новых таблиц.python manage.py migrate

REST_FRAMEWORK = {
    # ...
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    )
}

Кроме того, не забудьте дать исключение для UserCreate просмотра для аутентификации, переопределив глобальные настройки. UserCreate В polls/apiviews.py должен выглядеть следующим образом .

class UserCreate(generics.CreateAPIView):
    authentication_classes = ()
    permission_classes = ()
    serializer_class = UserSerializer

Обратите внимание на и освободить от глобальной схемы аутентификации.authentication_classes = ()  permission_classes = ()  UserCreate

Мы хотим убедиться, что токены создаются при создании пользователя в UserCreate представлении, поэтому мы обновляем UserSerializer. Измени свой serializers.py так

from rest_framework.authtoken.models import Token

class UserSerializer(serializers.ModelSerializer):

        class Meta:
            model = User
            fields = ('username', 'email', 'password')
            extra_kwargs = {'password': {'write_only': True}}

        def create(self, validated_data):
            user = User(
                email=validated_data['email'],
                username=validated_data['username']
            )
            user.set_password(validated_data['password'])
            user.save()
            Token.objects.create(user=user)
            return user

API входа 
Поскольку мы добавили rest_framework.authentication.TokenAuthentication, нам нужно установить такой заголовок для проверки подлинности. Нам нужен API, где пользователь может указать свое имя пользователя и пароль и получить токен обратно.Authorization: Token c2a84953f47288ac1943a3f389a6034e395ad940

Мы не будем добавлять сериализатор, потому что мы никогда не сохраняем токен с помощью этого API.

Добавьте представление и подключите его к URL.

# in apiviews.py
# ...
from django.contrib.auth import authenticate

class LoginView(APIView):
    permission_classes = ()

    def post(self, request,):
        username = request.data.get("username")
        password = request.data.get("password")
        user = authenticate(username=username, password=password)
        if user:
            return Response({"token": user.auth_token.key})
        else:
            return Response({"error": "Wrong Credentials"}, status=status.HTTP_400_BAD_REQUEST)


# in urls.py
# ...

from .apiviews import PollViewSet, ChoiceList, CreateVote, UserCreate, LoginView



urlpatterns = [
    path("login/", LoginView.as_view(), name="login"),
    # ...
]

Сделайте POST с правильным именем пользователя и паролем, и вы получите ответ, подобный этому.

{
    "token": "c300998d0e2d1b8b4ed9215589df4497de12000c"
}

Отправьте сообщение с неверным именем пользователя и паролем, и вы получите такой ответ с HTTP-статусом 400.

{
    "error": "Wrong Credentials"
}

Другой способ создания этой конечной точки входа в систему - использование obtain_auth_token метода, предоставленного DRF.

# in urls.py
# ...
from rest_framework.authtoken import views

urlpatterns = [
    path("login/", views.obtain_auth_token, name="login"),
    # ...
]

Мелкозернистый контроль доступа 
Попробуйте получить доступ к /polls/ API без заголовка. Вы получите сообщение об ошибке с кодом состояния HTTP из так.HTTP 401 Unauthorized

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

Добавьте заголовок авторизации , и вы получите доступ к API.Authorization: Token <your token>

Отныне мы будем использовать такой HTTP-заголовок во всех дальнейших запросах.Authorization: Token <your token>

У нас есть две оставшиеся вещи, которые мы должны обеспечить.

  • Прошедшие проверку пользователи могут создавать варианты только для созданных ими опросов.
  • Прошедшие проверку пользователи могут удалять только созданные им опросы.

Мы сделаем это, переопределив PollViewSet.destroy и ChoiceList.post.

В обоих случаях мы проверяем request.userпротив ожидаемого пользователя и повышаем , как PermissionDenied если бы он не совпадал.

Вы можете проверить это, выполнив УДАЛЕНИЕ кому-то еще Poll. Вы получите сообщение об ошибке и ответ.HTTP 403 Forbidden

{
    "detail": "You can not delete this poll."
}

Точно так же, пытаясь создать выбор для кого-то другого, Poll вы получите сообщение об ошибке и ответ HTTP 403 Forbidden

{
    "detail": "You can not create choice for this poll."
}

Следующие шаги: 
В следующей главе мы рассмотрим добавление тестов для нашего API и сериализаторов. Мы также рассмотрим, как использовать flake8и запускать наши тесты в среде CI.

Далее : Создание API с помощью Django и Django Rest Framework : Создание API с помощью Django и Django Rest Framework 

15 января 2019 г. 23:04 Теги - # django rest framework # django Категория - Django Kiwi standing on oval2685