Django rest框架:使用电子邮件而不是用户名获取身份验证令牌

Django rest框架:使用电子邮件而不是用户名获取身份验证令牌,django,authentication,django-rest-framework,Django,Authentication,Django Rest Framework,我正在做一个项目,为移动设备启用django rest框架身份验证。我使用默认令牌身份验证从发送用户名和密码的post请求中获取用户令牌 curl --data "username=username&password=password" http://127.0.0.1:8000/api/api-token-auth/ (api/api token auth/是使用“获取认证令牌”视图配置的url) 响应是用户令牌 {"token":"c8a8777aca969ea3a164967ec

我正在做一个项目,为移动设备启用django rest框架身份验证。我使用默认令牌身份验证从发送用户名和密码的post请求中获取用户令牌

curl --data "username=username&password=password" http://127.0.0.1:8000/api/api-token-auth/
(api/api token auth/是使用“获取认证令牌”视图配置的url)

响应是用户令牌

{"token":"c8a8777aca969ea3a164967ec3bb341a3495d234"}
我需要在帖子中使用电子邮件密码而不是用户名密码来获取用户令牌身份验证,或者两者都使用。我正在阅读自定义身份验证的文档。。。但我真的不太清楚。
这对我很有帮助。。。谢谢:)。

好的,我找到了一种使用电子邮件或用户名获取身份验证令牌的方法。。。这是序列化程序:

class AuthCustomTokenSerializer(serializers.Serializer):
    email_or_username = serializers.CharField()
    password = serializers.CharField()

    def validate(self, attrs):
        email_or_username = attrs.get('email_or_username')
        password = attrs.get('password')

        if email_or_username and password:
            # Check if user sent email
            if validateEmail(email_or_username):
                user_request = get_object_or_404(
                    User,
                    email=email_or_username,
                )

                email_or_username = user_request.username

            user = authenticate(username=email_or_username, password=password)

            if user:
                if not user.is_active:
                    msg = _('User account is disabled.')
                    raise exceptions.ValidationError(msg)
            else:
                msg = _('Unable to log in with provided credentials.')
                raise exceptions.ValidationError(msg)
        else:
            msg = _('Must include "email or username" and "password"')
            raise exceptions.ValidationError(msg)

        attrs['user'] = user
        return attrs
在email_或_username字段中,用户可以发送电子邮件或用户名,使用该功能,我们可以检查用户是否尝试使用电子邮件或用户名登录。然后,我们可以查询get用户实例是否有效,并对其进行身份验证

这就是观点

class ObtainAuthToken(APIView):
    throttle_classes = ()
    permission_classes = ()
    parser_classes = (
        parsers.FormParser,
        parsers.MultiPartParser,
        parsers.JSONParser,
    )

    renderer_classes = (renderers.JSONRenderer,)

    def post(self, request):
        serializer = AuthCustomTokenSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        token, created = Token.objects.get_or_create(user=user)

        content = {
            'token': unicode(token.key),
        }

        return Response(content)
然后:

curl --data "email_or_username=emailorusername&password=password" http://127.0.0.1:8000/api/my-api-token-auth/.

它准备好了。

有一种更干净的方法来获取用户令牌

{"token":"c8a8777aca969ea3a164967ec3bb341a3495d234"}
只需运行manage.py shell

然后

from rest_framework.authtoken.models import Token
from django.contrib.auth.models import User
u = User.objects.get(username='admin')
token = Token.objects.create(user=u)
print token.key

将这些要求写入settings.py

ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
要进行检查,请将此json格式请求发送到服务器:

{
    "username":"youremail@mail.domain",
    "password":"Pa$$w0rd"
}

更改库使用的默认序列化程序,例如在auth/serializers.py

from django.contrib.auth import authenticate
from django.utils.translation import gettext_lazy as _

from rest_framework import serializers


class MyAuthTokenSerializer(serializers.Serializer):
    email = serializers.EmailField(label=_("Email"))
    password = serializers.CharField(
        label=_("Password",),
        style={'input_type': 'password'},
        trim_whitespace=False
    )

    def validate(self, attrs):
        email = attrs.get('email')
        password = attrs.get('password')

        if email and password:
            user = authenticate(request=self.context.get('request'),
                                email=email, password=password)

            # The authenticate call simply returns None for is_active=False
            # users. (Assuming the default ModelBackend authentication
            # backend.)
            if not user:
                msg = _('Unable to log in with provided credentials.')
                raise serializers.ValidationError(msg, code='authorization')
        else:
            msg = _('Must include "username" and "password".')
            raise serializers.ValidationError(msg, code='authorization')

        attrs['user'] = user
        return attrs
from rest_framework.authtoken import views as auth_views
from rest_framework.compat import coreapi, coreschema
from rest_framework.schemas import ManualSchema

from .serializers import MyAuthTokenSerializer


class MyAuthToken(auth_views.ObtainAuthToken):
    serializer_class = MyAuthTokenSerializer
    if coreapi is not None and coreschema is not None:
        schema = ManualSchema(
            fields=[
                coreapi.Field(
                    name="email",
                    required=True,
                    location='form',
                    schema=coreschema.String(
                        title="Email",
                        description="Valid email for authentication",
                    ),
                ),
                coreapi.Field(
                    name="password",
                    required=True,
                    location='form',
                    schema=coreschema.String(
                        title="Password",
                        description="Valid password for authentication",
                    ),
                ),
            ],
            encoding="application/json",
        )


obtain_auth_token = MyAuthToken.as_view()
from .views import obtain_auth_token
urlpatterns = [
    re_path(r'^api-token-auth/', obtain_auth_token),
]
覆盖视图,例如在auth/views.py

from django.contrib.auth import authenticate
from django.utils.translation import gettext_lazy as _

from rest_framework import serializers


class MyAuthTokenSerializer(serializers.Serializer):
    email = serializers.EmailField(label=_("Email"))
    password = serializers.CharField(
        label=_("Password",),
        style={'input_type': 'password'},
        trim_whitespace=False
    )

    def validate(self, attrs):
        email = attrs.get('email')
        password = attrs.get('password')

        if email and password:
            user = authenticate(request=self.context.get('request'),
                                email=email, password=password)

            # The authenticate call simply returns None for is_active=False
            # users. (Assuming the default ModelBackend authentication
            # backend.)
            if not user:
                msg = _('Unable to log in with provided credentials.')
                raise serializers.ValidationError(msg, code='authorization')
        else:
            msg = _('Must include "username" and "password".')
            raise serializers.ValidationError(msg, code='authorization')

        attrs['user'] = user
        return attrs
from rest_framework.authtoken import views as auth_views
from rest_framework.compat import coreapi, coreschema
from rest_framework.schemas import ManualSchema

from .serializers import MyAuthTokenSerializer


class MyAuthToken(auth_views.ObtainAuthToken):
    serializer_class = MyAuthTokenSerializer
    if coreapi is not None and coreschema is not None:
        schema = ManualSchema(
            fields=[
                coreapi.Field(
                    name="email",
                    required=True,
                    location='form',
                    schema=coreschema.String(
                        title="Email",
                        description="Valid email for authentication",
                    ),
                ),
                coreapi.Field(
                    name="password",
                    required=True,
                    location='form',
                    schema=coreschema.String(
                        title="Password",
                        description="Valid password for authentication",
                    ),
                ),
            ],
            encoding="application/json",
        )


obtain_auth_token = MyAuthToken.as_view()
from .views import obtain_auth_token
urlpatterns = [
    re_path(r'^api-token-auth/', obtain_auth_token),
]
连接url,例如在auth/url.py中

from django.contrib.auth import authenticate
from django.utils.translation import gettext_lazy as _

from rest_framework import serializers


class MyAuthTokenSerializer(serializers.Serializer):
    email = serializers.EmailField(label=_("Email"))
    password = serializers.CharField(
        label=_("Password",),
        style={'input_type': 'password'},
        trim_whitespace=False
    )

    def validate(self, attrs):
        email = attrs.get('email')
        password = attrs.get('password')

        if email and password:
            user = authenticate(request=self.context.get('request'),
                                email=email, password=password)

            # The authenticate call simply returns None for is_active=False
            # users. (Assuming the default ModelBackend authentication
            # backend.)
            if not user:
                msg = _('Unable to log in with provided credentials.')
                raise serializers.ValidationError(msg, code='authorization')
        else:
            msg = _('Must include "username" and "password".')
            raise serializers.ValidationError(msg, code='authorization')

        attrs['user'] = user
        return attrs
from rest_framework.authtoken import views as auth_views
from rest_framework.compat import coreapi, coreschema
from rest_framework.schemas import ManualSchema

from .serializers import MyAuthTokenSerializer


class MyAuthToken(auth_views.ObtainAuthToken):
    serializer_class = MyAuthTokenSerializer
    if coreapi is not None and coreschema is not None:
        schema = ManualSchema(
            fields=[
                coreapi.Field(
                    name="email",
                    required=True,
                    location='form',
                    schema=coreschema.String(
                        title="Email",
                        description="Valid email for authentication",
                    ),
                ),
                coreapi.Field(
                    name="password",
                    required=True,
                    location='form',
                    schema=coreschema.String(
                        title="Password",
                        description="Valid password for authentication",
                    ),
                ),
            ],
            encoding="application/json",
        )


obtain_auth_token = MyAuthToken.as_view()
from .views import obtain_auth_token
urlpatterns = [
    re_path(r'^api-token-auth/', obtain_auth_token),
]

你准备好出发了

您的应用程序是否已经可以使用电子邮件和密码登录?或者这是您为应用程序实现的第一个身份验证方法吗?您好。。。是第一种身份验证方法,我以前没有实现过其他。。。现在我使用默认的获取令牌方法,使用用户名和密码。。。但是,在移动设备中,我需要使用电子邮件和密码获得令牌身份验证。您好!我尝试了您的解决方案,但它抱怨缺少validateEmail和authenticate方法。你能分享一下丢失的代码吗?谢谢是DRF设置还是设置的全局部分。我发现发送json和使用字段“username”,但值是email,仍然有效。不需要在settings.py中添加ACCOUNT_uuu。这似乎是django allauth提供的,对django无效。这是获取令牌的一种方式,但不是OP的问题。我认为,这比这要好得多。另外,您可以添加CSRF代币。