如何使用SessionAuthentication使用Django rest框架创建登录rest API?

如何使用SessionAuthentication使用Django rest框架创建登录rest API?,django,django-rest-framework,Django,Django Rest Framework,我想做一个RESTAPI,以便能够使用如下请求登录到我的Django应用程序(从Android应用程序) curl -X POST -d "username=myusername&password=mypassword" http://localhost:12345/rest/api-auth/login/ 它应该返回一个会话id,我可以在以后的请求中使用它。看起来我应该使用SessionAuthentication身份验证方案,但实际上是这样的 我知道,但我不想使用任何其他应用程序

我想做一个RESTAPI,以便能够使用如下请求登录到我的Django应用程序(从Android应用程序)

curl -X POST -d "username=myusername&password=mypassword" http://localhost:12345/rest/api-auth/login/
它应该返回一个会话id,我可以在以后的请求中使用它。看起来我应该使用SessionAuthentication身份验证方案,但实际上是这样的

我知道,但我不想使用任何其他应用程序


任何建议/指针?

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

如果打算通过在POST数据上传递用户名和密码来访问某个端点,则可以执行以下操作:

url.py

urlpatterns = [
    url(r'^stuff/', views.MyView.as_view()),
    ...
]
    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)
视图.py

urlpatterns = [
    url(r'^stuff/', views.MyView.as_view()),
    ...
]
    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'

所以我必须为我的API做一个自定义视图?Django REST框架中没有包含这样的东西?谢谢,但是我如何使用它呢?我复制了你的代码,在我的url.py中添加了
url(r'^rest/login/$,views.ExampleView.as_view()),
,并在
用户中获得了
“非类型”对象不可编辑的
,\uu=super(MyBasicAuthentication,self)。尝试
curl-I-X POST时验证(请求)
http://127.0.0.1:8000/rest/login/ -d“用户=用户&密码=通过”
您可以这样使用特定的实现:
curl-i-xgethttp://127.0.0.1:8000/rest/login/ -u user:pass
这就是使用基本身份验证对curl进行身份验证的方式。似乎视图没有返回(我没有从
curl-I-X get得到响应http://127.0.0.1:8000/rest/login/ -u用户:通过
)。我怎样才能从中获得会话?@jul我现在也有同样的问题,我发布了一个关于这个问题的问题,但我没有得到答案,你是如何实现的?你覆盖def authenticate()并等待比所有时间都能获得用户名和密码,但我在切换到新url时没有输入用户名和密码,我只有会话ID,所以你的变种不起作用了