用户注册和通过电子邮件地址而不是用户名进行身份验证

时间:2012-03-04 08:05:33

标签: django authentication

我不想编写自定义身份验证后端,我认为这个常见任务必须已经被某些第三方应用程序解决了。

我做了一些谷歌搜索和浏览,但发现只有https://bitbucket.org/hakanw/django-email-usernames/wiki/Home这是相当古老的(2008年)。还有其他替代方案吗?

3 个答案:

答案 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'
)