gpt4 book ai didi

django - 如何在 `email` 中使用 "django-rest-framework-simplejwt"而不是 `username` 来生成 token ?

转载 作者:行者123 更新时间:2023-12-03 16:16:56 25 4
gpt4 key购买 nike

在 django-rest-framework-simplejwt 插件中 usernamepassword默认使用。但我想用 email而不是 username .所以,我确实喜欢以下内容:

在序列化程序中:

class MyTokenObtainSerializer(Serializer):
username_field = User.EMAIL_FIELD

def __init__(self, *args, **kwargs):
super(MyTokenObtainSerializer, self).__init__(*args, **kwargs)

self.fields[self.username_field] = CharField()
self.fields['password'] = PasswordField()

def validate(self, attrs):
# self.user = authenticate(**{
# self.username_field: attrs[self.username_field],
# 'password': attrs['password'],
# })
self.user = User.objects.filter(email=attrs[self.username_field]).first()
print(self.user)

if not self.user:
raise ValidationError('The user is not valid.')

if self.user:
if not self.user.check_password(attrs['password']):
raise ValidationError('Incorrect credentials.')
print(self.user)
# Prior to Django 1.10, inactive users could be authenticated with the
# default `ModelBackend`. As of Django 1.10, the `ModelBackend`
# prevents inactive users from authenticating. App designers can still
# allow inactive users to authenticate by opting for the new
# `AllowAllUsersModelBackend`. However, we explicitly prevent inactive
# users from authenticating to enforce a reasonable policy and provide
# sensible backwards compatibility with older Django versions.
if self.user is None or not self.user.is_active:
raise ValidationError('No active account found with the given credentials')

return {}

@classmethod
def get_token(cls, user):
raise NotImplemented(
'Must implement `get_token` method for `MyTokenObtainSerializer` subclasses')


class MyTokenObtainPairSerializer(MyTokenObtainSerializer):
@classmethod
def get_token(cls, user):
return RefreshToken.for_user(user)

def validate(self, attrs):
data = super(MyTokenObtainPairSerializer, self).validate(attrs)

refresh = self.get_token(self.user)

data['refresh'] = text_type(refresh)
data['access'] = text_type(refresh.access_token)

return data

查看:
class MyTokenObtainPairView(TokenObtainPairView):
"""
Takes a set of user credentials and returns an access and refresh JSON web
token pair to prove the authentication of those credentials.
"""
serializer_class = MyTokenObtainPairSerializer

它有效!!

现在我的问题是,我怎样才能更有效地做到这一点?任何人都可以对此提出建议吗?提前致谢。

最佳答案

这个答案是为 future 的读者准备的,因此包含额外的信息。

为了简化身份验证后端,您需要 Hook 多个类。我建议做 选项 1 (以及可选的 选项 3 ,您的简化版本)如下。在继续阅读之前,请注意以下几点:

  • 注 1: django 不会根据需要强制执行电子邮件或在用户创建时是唯一的(您可以覆盖它,但它是题外话)!因此,选项 3(您的实现)可能会给您带来重复电子邮件的问题。
  • 注释 1b:使用 User.objects.filter(email__iexact=...)以不区分大小写的方式匹配电子邮件。
  • 注释 1c:使用 get_user_model()如果您将来替换默认用户模型,这对于初学者来说确实是一个救星!
  • 注 2:避免将用户打印到控制台。您可能正在打印敏感数据。

  • 至于3个选项:
  • 使用 f.e. 调整 django 身份验证后端class EmailModelBackend(ModelBackend)并替换身份验证功能。
  • 不调整代币声明
  • 不依赖于 JWT 类/中间件(SimpleJWT、JWT 或其他)
  • 还调整了其他认证类型​​(Session/Cookie/non-API auth 等)
  • 所需的输入参数仍然是 用户名 ,示例如下。如果您不喜欢它,请进行调整,但要小心。 (可能会破坏您的导入/插件并且不是必需的!)
  • 替换 Django authenticate(username=, password=, **kwarg)来自 django.contrib.auth
  • 不调整代币声明
  • 您还需要替换 token 后端,因为它应该使用不同的身份验证,就像您在上面所做的那样。
  • 不使用 authenticate(...) 调整其他应用程序, 仅替换 JWT 身份验证(如果您这样设置)
    参数不是必需的,因此不建议使用此选项)。
  • 实现 MyTokenObtainPairSerializer以电子邮件为 claim 。
  • 现在电子邮件作为 JWT 数据(而不是 id)发回。
  • 与选项 1 一起,您的应用程序身份验证已变得与用户名无关。

  • 选项 1 (注意这也允许用户名!!):
    from django.contrib.auth import get_user_model
    from django.contrib.auth.backends import ModelBackend
    from django.db.models import Q

    class EmailorUsernameModelBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
    UserModel = get_user_model()
    try:
    user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
    except UserModel.DoesNotExist:
    return None
    else:
    if user.check_password(password):
    return user
    return None

    选项 2:
    跳过,留给读者而不是建议。

    选项 3:
    您似乎已经在上面介绍了这一点。

    注:您不必定义 MyTokenObtainPairView ,您可以使用 TokenObtainPairView(serializer_class=MyTokenObtainPairSerializer).as_view()在你的 urls.py 中。覆盖使用的小简化 token 序列化器 .

    注 2:您也可以在 settings.py(或设置文件)中指定标识声明和添加的数据以使用电子邮件。这将使您的前端应用程序也使用电子邮件进行声明(而不是默认 用户 .id)
    SIMPLE_JWT = {
    'USER_ID_FIELD': 'id', # model property to attempt claims for
    'USER_ID_CLAIM': 'user_id', # actual keyword in token data
    }

    但是,请注意创作者给出的独特性警告:

    For example, specifying a "username" or "email" field would be a poor choice since an account's username or email might change depending on how account management in a given service is designed.



    如果你能保证唯一性,你就万事大吉了。

    关于django - 如何在 `email` 中使用 "django-rest-framework-simplejwt"而不是 `username` 来生成 token ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54157056/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com