我正在开发一个项目,为移动设备启用 django Rest 框架身份验证。我使用默认令牌身份验证从发送用户名和密码的发布请求中获取用户令牌。
curl --data "username=username&password=password" http://127.0.0.1:8000/api/api-token-auth/
(api/api-token-auth/是obtain_auth_token视图配置的url)
urlpatterns = [
url(r'^api/api-token-auth/', obtain_auth_token),
url(r'^', include(router.urls)),
]
响应是用户令牌。
{"token":"c8a8777aca969ea3a164967ec3bb341a3495d234"}
我需要使用帖子上的电子邮件密码而不是用户名密码或两者来获取用户令牌身份验证。我正在阅读自定义身份验证的文档http://www.django-rest-framework.org/api-guide/authentication/#custom-authentication...但实际上,我并不是很清楚。 这对我很有帮助...谢谢:).
好的,我找到了一种使用电子邮件或用户名获取身份验证令牌的方法...这是序列化器:
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_or_username 字段中,用户可以发送电子邮件或用户名,并使用函数 validateEmail(),我们可以检查用户是否正在尝试使用电子邮件或用户名登录。然后,我们可以进行查询以获取用户实例(如果有效),并对其进行身份验证。
这就是景色。
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/.
准备好了。
将这些要求写入您的settings.py
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
要进行检查,请将此 json 格式请求发送到您的服务器:
{
"username":"[email protected]",
"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 "email" and "password".')
raise serializers.ValidationError(msg, code='authorization')
attrs['user'] = user
return attrs
覆盖视图,例如在auth/views.py
中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()
例如在 auth/urls.py
中连接 urlfrom .views import obtain_auth_token
urlpatterns = [
re_path(r'^api-token-auth/', obtain_auth_token),
]
你就可以出发了!!
@udeep shrestha 解决方案几乎可以工作,但您需要更改
validate
方法以手动使用 Django 的用户身份验证模型来手动验证密码:
from rest_framework import serializers
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import User
class UserSerializer(serializers.Serializer):
email = serializers.EmailField()
username = serializers.CharField()
first_name = serializers.CharField()
last_name = serializers.CharField()
is_staff = serializers.BooleanField()
date_joined = serializers.DateTimeField()
class CustomAuthTokenSerializer(serializers.Serializer):
email = serializers.EmailField(
label=_("Email"),
write_only=True
)
password = serializers.CharField(
label=_("Password"),
style={"input_type": "password"},
trim_whitespace=False,
write_only=True
)
token = serializers.CharField(
label=_("Token"),
read_only=True
)
def validate(self, attrs):
email = attrs.get("email")
password = attrs.get("password")
passwords_match = False
if email and password:
user = User.objects.get(email=email)
if user:
passwords_match = user.check_password(password)
# The authenticate call simply returns None for is_active=False
# users. (Assuming the default ModelBackend authentication
# backend.)
if not user or not passwords_match:
msg = _("Unable to log in with provided credentials.")
raise serializers.ValidationError(msg, code="authorization")
else:
msg = _("Must include 'email' and 'password'.")
raise serializers.ValidationError(msg, code="authorization")
attrs["user"] = user
return attrs
有一种更干净的方式来获取用户令牌。
只需运行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