gpt4 book ai didi

python - 在 Django 中使用电子邮件地址或用户名登录用户

转载 作者:IT老高 更新时间:2023-10-28 20:26:15 24 4
gpt4 key购买 nike

我正在尝试创建一个身份验证后端,以允许我的用户使用他们的电子邮件地址或他们在 Django 1.6 中的用户名和自定义用户模型登录。当我使用用户名登录但由于某种原因不使用电子邮件时,后端工作。有什么我忘记做的吗?

from django.conf import settings
from django.contrib.auth.models import User

class EmailOrUsernameModelBackend(object):
"""
This is a ModelBacked that allows authentication with either a username or an email address.

"""
def authenticate(self, username=None, password=None):
if '@' in username:
kwargs = {'email': username}
else:
kwargs = {'username': username}
try:
user = User.objects.get(**kwargs)
if user.check_password(password):
return user
except User.DoesNotExist:
return None

def get_user(self, username):
try:
return User.objects.get(pk=username)
except User.DoesNotExist:
return None

编辑:正如建议的那样,我从 ModelBackend 继承并将其安装在我的设置中在我的设置中,我有这个 AUTHENTICATION_BACKENDS = ( 'users.backends', 'django.contrib.auth.backends.ModelBackend', )我已将后端更改为:

from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.auth.backends import ModelBackend
class EmailOrUsernameModelBackend(ModelBackend):
"""
This is a ModelBacked that allows authentication with either a username or an email address.

"""
def authenticate(self, username=None, password=None):
if '@' in username:
kwargs = {'email': username}
else:
kwargs = {'username': username}
try:
user = User.objects.get(**kwargs)
if user.check_password(password):
return user
except User.DoesNotExist:
return None

def get_user(self, username):
try:
return User.objects.get(pk=username)
except User.DoesNotExist:
return None

现在我得到一个模块“用户”没有定义“后端”属性/类错误。

最佳答案

另一个解决方案:

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q


class EmailOrUsernameModelBackend(ModelBackend):
"""
Authentication backend which allows users to authenticate using either their
username or email address

Source: https://stackoverflow.com/a/35836674/59984
"""

def authenticate(self, request, username=None, password=None, **kwargs):
# n.b. Django <2.1 does not pass the `request`

user_model = get_user_model()

if username is None:
username = kwargs.get(user_model.USERNAME_FIELD)

# The `username` field is allows to contain `@` characters so
# technically a given email address could be present in either field,
# possibly even for different users, so we'll query for all matching
# records and test each one.
users = user_model._default_manager.filter(
Q(**{user_model.USERNAME_FIELD: username}) | Q(email__iexact=username)
)

# Test whether any matched user has the provided password:
for user in users:
if user.check_password(password):
return user
if not users:
# Run the default password hasher once to reduce the timing
# difference between an existing and a non-existing user (see
# https://code.djangoproject.com/ticket/20760)
user_model().set_password(password)

修复:

  • 默认情况下,用户名字段中没有禁止@,所以除非自定义User模型禁止@符号,否则不能用于区分用户名和邮箱.
  • 从技术上讲,可以有两个用户使用同一个电子邮件,一个在电子邮件字段中,另一个在用户名中。除非这种可能性受到限制,否则如果 UserModel._default_manager.get(Q(username__iexact=username) | Q(email__iexact=使用用户名))
  • 使用 except: 捕获任何异常通常是不好的做法

缺点 - 如果有两个用户使用相同的电子邮件,一个在用户名中,另一个在电子邮件中,并且他们具有相同的密码,那么很容易验证第一个匹配项。我想这种可能性极小。

另请注意:任何方法都应该在 User 模型中强制执行唯一的 email 字段,因为默认的 User 模型没有定义唯一的电子邮件,这将导致使用 User.objects.get(email__iexact="...") 或验证第一个匹配项时未处理的异常。在任何情况下,使用电子邮件登录都假定电子邮件是唯一的。

关于python - 在 Django 中使用电子邮件地址或用户名登录用户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25316765/

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