首先,这不是如何对电子邮件/密码对进行身份验证的问题,而是如何生成逻辑,如果您愿意,还可以生成漂亮的数据结构。
我想在给定的django项目中使用电子邮件作为用户名。但是,我无法重新使用auth.User模型提供的字段,原因至少有两个:
auth.User.username的字段max_length是30个字符,对于某些电子邮件地址可能不够。
auth.User.email不是唯一的 - 显然不能满足前提条件,即用户名必须是唯一的。
这里一个显而易见的方法是将用户名存储在自定义配置文件中,该配置文件链接到auth.User。在这种情况下,我们必须处理以下问题:
以下问题源于提议的解决方案:
为了在火灾中加油,django开发商不可能在任何可预见的未来修复此限制 - 请参阅http://code.djangoproject.com/ticket/11365
所以问题是:有没有其他方法可以做到这一点,你看到上面提出的解决方案有任何其他缺点吗?
谢谢!
答案 0 :(得分:5)
我的客户有一个自1995年以来一直在增加的商业网站(是的,我们在这里谈论早期采用者)。无论如何,他们已经建立了一个已建立的用户群,并且名称完全不符合Django对用户名的想法。
我看了几种方法来处理它,它们都感觉像黑客(这是2007年的夏天),所以我说搞砸它并直接攻击contrib.auth.models.User。我只需更改大约10行代码,增加字段大小,并调整验证器。从那以后我们做了两次升级 - 0.97-pre => 1.0,和1.0 => 1.1.1 - 并且每次只需要大约15分钟来“移植黑客”。
它不漂亮,而且我可能会像这样在地狱中燃烧,但这样做的时间比我能想到的任何其他东西花费的时间更短,前向端口完全没有问题。
答案 1 :(得分:2)
您可能想看看Satchmo如何处理这个问题:
http://bitbucket.org/chris1610/satchmo/src/tip/satchmo/apps/satchmo_store/accounts/email-auth.py
和
http://bitbucket.org/chris1610/satchmo/src/533a63f955f8/satchmo/apps/satchmo_utils/unique_id.py
答案 2 :(得分:1)
我写了一个关于我对这个问题的解决方案的解释:Django Authentication using an Email Address。它基本上包括:
我的解决方案仍有2个问题。首先,手动创建数据库索引并不好。其次,电子邮件仍然限制在75个字符(我没有任何问题移植系统有大约8,000个用户)。但是,它与Django和第三方应用程序的其余部分相当不错。
答案 3 :(得分:0)
我也必须承认我会在地狱中燃烧。我最近部署了一个小应用程序,我将用户的电子邮件强制插入,将其切成30个字符并将其设置为用户名。我以为地狱,赔率是多少?并经历过它。拿了几行代码,瞧不起。
我认为75字符的上限是这样设置的,因为人们通常没有长时间的个人电子邮件。这只是空间保护的问题,因为所有那些未使用的字节都将被保留(即NULL和更短/更小的值不是免费的)。
答案 4 :(得分:0)
我只使用this djangosnippet,用户可以使用他们的用户名或电子邮件 但它不能解决75个字符的限制,只是一个方便的片段。
答案 5 :(得分:0)
我写了一个基于Dominique答案的解决方案,其中包括安全性改进和一些额外的功能,如区分大小写的身份验证。如果您愿意,可以install it directly from pypi:
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
from django.conf import settings
###################################
""" DEFAULT SETTINGS + ALIAS """
###################################
try:
am = settings.AUTHENTICATION_METHOD
except:
am = 'both'
try:
cs = settings.AUTHENTICATION_CASE_SENSITIVE
except:
cs = 'both'
#####################
""" EXCEPTIONS """
#####################
VALID_AM = ['username', 'email', 'both']
VALID_CS = ['username', 'email', 'both', 'none']
if (am not in VALID_AM):
raise Exception("Invalid value for AUTHENTICATION_METHOD in project "
"settings. Use 'username','email', or 'both'.")
if (cs not in VALID_CS):
raise Exception("Invalid value for AUTHENTICATION_CASE_SENSITIVE in project "
"settings. Use 'username','email', 'both' or 'none'.")
############################
""" OVERRIDDEN METHODS """
############################
class DualAuthentication(ModelBackend):
"""
This is a ModelBacked that allows authentication
with either a username or an email address.
"""
def authenticate(self, username=None, password=None):
UserModel = get_user_model()
try:
if ((am == 'email') or (am == 'both')):
if ((cs == 'email') or cs == 'both'):
kwargs = {'email': username}
else:
kwargs = {'email__iexact': username}
user = UserModel.objects.get(**kwargs)
else:
raise
except:
if ((am == 'username') or (am == 'both')):
if ((cs == 'username') or cs == 'both'):
kwargs = {'username': username}
else:
kwargs = {'username__iexact': username}
user = UserModel.objects.get(**kwargs)
finally:
try:
if user.check_password(password):
return user
except:
# Run the default password hasher once to reduce the timing
# difference between an existing and a non-existing user.
UserModel().set_password(password)
return None
def get_user(self, username):
UserModel = get_user_model()
try:
return UserModel.objects.get(pk=username)
except UserModel.DoesNotExist:
return None
答案 6 :(得分:0)
对于没有更改模型的两种身份验证[用户名,电子邮件],只需添加后端: