Как я могу использовать SessionAuthentication для создания API-интерфейса для входа в систему с помощью Django Rest Framework?

Я хочу сделать API для отдыха, чтобы иметь возможность войти в мое приложение Django (из приложения для Android), используя запрос типа

curl -X POST -d "username=myusername&password=mypassword" http://localhost:12345/rest/api-auth/login/

который должен возвращать идентификатор сеанса, который я могу использовать в будущих запросах. Кажется, мне следует использовать схему аутентификации SessionAuthentication, но no doc об этом.

Мне известен этот вопрос, но я не хочу использовать какое-либо другое приложение.

Любое предложение/указатель?


person jul    schedule 15.05.2014    source источник


Ответы (2)


Ресурс /api-auth/login/ предназначен только для аутентификации в API для просмотра. Чтобы использовать сеансовую аутентификацию, необходимо сначала создать сеанс. У вас должен быть ресурс входа в систему, который принимает учетные данные пользователя и аутентифицирует пользователя с помощью системы аутентификации Django. При запросе этого ресурса клиент получит заголовок cookie. Файл cookie и токен csrf должны использоваться в будущих запросах.

curl -v -X POST https://example.com/api/user/login/ -d 'username=user&password=pass'

...

> Set-Cookie:  csrftoken=TqIuhp8oEP9VY32tUDcfQyUwn3cqpYCa; expires=Fri, 15-May-2015 12:48:57 GMT; Max-Age=31449600; Path=/
> Set-Cookie:  sessionid=4yb4s456lbvd974oijbdha7k3l6g52q3; expires=Fri, 30-May-2014 12:48:57 GMT; Max-Age=1209600; Path=/

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

from django.contrib.auth import login

from rest_framework.authentication import BasicAuthentication, SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView


class MyBasicAuthentication(BasicAuthentication):

    def authenticate(self, request):
        user, _ = super(MyBasicAuthentication, self).authenticate(request)
        login(request, user)
        return user, _


class ExampleView(APIView):
    authentication_classes = (SessionAuthentication, MyBasicAuthentication)
    permission_classes = (IsAuthenticated,)

    def get(self, request, format=None):
        content = {
            'user': unicode(request.user),
            'auth': unicode(request.auth),  # None
        }
        return Response(content)
person YAtOff    schedule 16.05.2014
comment
Итак, мне нужно сделать собственное представление для моего API? нет такой вещи, включенной в структуру Django REST? - person jul; 16.05.2014
comment
Спасибо, но как я могу это использовать? Я скопировал ваш код, добавил url(r'^rest/login/$', views.ExampleView.as_view()), в свой urls.py и получил 'NoneType' object is not iterable в user, _ = super(MyBasicAuthentication, self).authenticate(request) при попытке curl -i -X POST http://127.0.0.1:8000/rest/login/ -d "user=user&password=pass" - person jul; 16.05.2014
comment
Вы можете использовать эту конкретную реализацию следующим образом: curl -i -X GET http://127.0.0.1:8000/rest/login/ -u user:pass Вот как вы выполняете аутентификацию с помощью curl, используя обычную аутентификацию. - person YAtOff; 16.05.2014
comment
Кажется, что представление не возвращается (я не получаю ответа от curl -i -X GET http://127.0.0.1:8000/rest/login/ -u user:pass). И как я могу получить сеанс от этого? - person jul; 17.05.2014
comment
@jul У меня сейчас та же проблема, я задал вопрос об этом и не получил ответа, как вы это реализовали? - person Lara; 07.08.2014
comment
Я использовал TokenAuthentication в конце. - person jul; 07.08.2014
comment
Я не знаю, как с вами связаться, но вы не могли бы мне помочь?! Я потерялся :( - person Lara; 07.08.2014
comment
/rest/api -› Страница не найдена (404) - person Cerin; 24.01.2020
comment
Метод def get связан с http-запросом, сделанным в этом представлении? Если да, то можно ли сохранить этот метод в другом месте для повторного использования другими представлениями вместо того, чтобы помещать его в каждое отдельное представление, где вы хотите убедиться, что пользователь вошел в систему? - person Seb; 24.04.2020
comment
Как добавить продолжительность сеанса? Например, аннулировать сеанс через определенное время? - person Kshitij Singh; 17.07.2020

Если вы хотите получить доступ к какой-либо конечной точке, передав имя пользователя и пароль в данных POST, вы можете сделать следующее:

urls.py

urlpatterns = [
    url(r'^stuff/', views.MyView.as_view()),
    ...
]

views.py

    from django.contrib.auth.models import User
    from rest_framework import viewsets
    from rest_framework.response import Response
    from rest_framework.views import APIView    
    from rest_framework.permissions import IsAuthenticated
    from rest_framework import exceptions
    from rest_framework import authentication
    from django.contrib.auth import authenticate, get_user_model
    from rest_framework.authentication import BasicAuthentication, 
SessionAuthentication


class ExampleAuthentication(authentication.BaseAuthentication):

    def authenticate(self, request):

        # Get the username and password
        username = request.data.get('username', None)
        password = request.data.get('password', None)

        if not username or not password:
            raise exceptions.AuthenticationFailed(_('No credentials provided.'))

        credentials = {
            get_user_model().USERNAME_FIELD: username,
            'password': password
        }

        user = authenticate(**credentials)

        if user is None:
            raise exceptions.AuthenticationFailed(_('Invalid username/password.'))

        if not user.is_active:
            raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))


    return (user, None)  # authentication successful


class MyView(APIView):
    authentication_classes = (SessionAuthentication, ExampleAuthentication,)
    permission_classes = (IsAuthenticated,)

    def post(self, request, format=None):    
        content = {
            'user': unicode(request.user),
            'auth': unicode(request.auth),  # None
        }
        return Response(content)

Скручивание

curl -v -X POST http://localhost:8000/stuff/ -d 'username=my_username&password=my_password'
person Slipstream    schedule 09.09.2017
comment
вы переопределяете def authentication () и ждете, чем все время можете получить имя пользователя и пароль, но я не ввожу имя пользователя и пароль при переходе на новый URL-адрес, у меня есть только sessionId, поэтому ваш вариант не работает - person Vadim; 23.04.2021