我不想编写自定义身份验证后端,我认为这个常见任务必须已经被某些第三方应用程序解决了。
我做了一些谷歌搜索和浏览,但发现只有https://bitbucket.org/hakanw/django-email-usernames/wiki/Home这是相当古老的(2008年)。还有其他替代方案吗?
答案 0 :(得分:7)
你说,"我不想写自定义身份验证后端"但是custom authentication backend正是Django期望你解决这个问题的方式,而且,它非常简单 - 比安装第三方应用程序简单得多。
这是一种简单的方法,用户有一个电子邮件地址,存储在内置email
对象的User
字段中。
首先,考虑区分大小写。即使电子邮件地址的本地部分(@符号前面的部分)可能区分大小写(取决于电子邮件提供商),Django的内置auth
应用程序也会对待e - 邮件地址不区分大小写(例如,在决定响应密码重置请求时向哪些用户发送电子邮件时)。因此,对他们来说也是最好的对待他们。
其次,确保两个用户无法共享同一个电子邮件地址。您可以在数据库中手动执行此操作:
ALTER TABLE auth_user ADD UNIQUE INDEX (email);
或者如果您使用的是South,请为您调用db.create_unique('auth_user', 'email')
的auth
应用程序进行架构迁移。
要强制使用不区分大小写的唯一性,应确保email
字段上的排序规则不区分大小写。我发现它已经存在了,但你可能会做类似的事情:
ALTER TABLE auth_user MODIFY email VARCHAR(75) COLLATE utf8_general_ci;
(如果您不支持international e-mail addresses,请ascii_general_ci
。)
第三,define your authentication backend,也许在mysite/backends.py
:
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User
class EmailAuthenticationBackend(ModelBackend):
"""
Authenticate against django.contrib.auth.models.User using
e-mail address instead of username.
"""
def authenticate(self, username=None, password=None):
try:
user = User.objects.get(email__iexact = username)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
第四,将您的身份验证后端添加到settings.py
:
AUTHENTICATION_BACKENDS = ('mysite.backends.EmailAuthenticationBackend',)
答案 1 :(得分:2)
您可以使用该电子邮件作为用户名,即用户输入他们的电子邮件,并将其分配给用户名和电子邮件属性(或jus用户名,并留下电子邮件空白,更好地满足您的需求)。
我在其中一个网站上使用这种方法,它运行正常。它基于django.contrib.auth,这可能是最成熟和最常用的解决方案,所以我会尝试使用它。
您提到的库非常简单,但它引入了一些自定义。它提供的内容可能是通过我提出的建议来实现的。我的解决方案更简单,他们的解决方案更清晰,由您来决定:)
答案 2 :(得分:1)
您不需要使用应用程序。这是一件非常简单的事情。在我的项目中,每个用户都有一个配置文件,每个配置文件可以有多个电子邮件。用户可以使用他的任何电子邮件地址登录系统。
class EmailAuthBackend(ModelBackend):
'''Logs users using email addresses rather than usernames
'''
def authenticate(self, username=None, password=None):
'''Try to log users on using any of their emails
facebook does that too.
username is an email address.
'''
try:
email = Email.objects.get(email=username)
user_profile = email.content_object
if user_profile.user.check_password(password):
return user_profile.user
except Email.DoesNotExist:
return None
我还在通过电话号码添加登录,人们显然比电子邮件地址更好地记住他们的电话号码。所以你可以替换说
的行email = Email.objects.get(email=username)
带
phone = Phone.objects.get(phone=username)
我通常在contrib one上面有自定义身份验证后端,因此当这个后端无法进行身份验证时,它可以作为故障转移。
AUTHENTICATION_BACKENDS = (
# an email logon backend
'account.backends.EmailAuthBackend',
# django builtin auth will be diabled in the future
'django.contrib.auth.backends.ModelBackend'
)