Django-使用电子邮件登录

Django-使用电子邮件登录,django,Django,我希望django通过电子邮件而不是用户名来验证用户。一种方法是提供电子邮件值作为用户名值,但我不希望这样。原因是,我有一个url/profile/,因此我不能有一个url/profile/abcd@gmail.com/ 另一个原因是所有电子邮件都是唯一的,但有时用户名已经被使用了。因此,我将自动创建用户名为fullName\u ID 我怎样才能更改让Django通过电子邮件进行身份验证 这就是我创建用户的方式 username = `abcd28` user_email = `abcd@gma

我希望django通过电子邮件而不是用户名来验证用户。一种方法是提供电子邮件值作为用户名值,但我不希望这样。原因是,我有一个url
/profile/
,因此我不能有一个url
/profile/abcd@gmail.com/

另一个原因是所有电子邮件都是唯一的,但有时用户名已经被使用了。因此,我将自动创建用户名为
fullName\u ID

我怎样才能更改让Django通过电子邮件进行身份验证

这就是我创建用户的方式

username = `abcd28`
user_email = `abcd@gmail.com`
user = User.objects.create_user(username, user_email, user_pass)
这就是我登录的方式

email = request.POST['email']
password = request.POST['password']
username = User.objects.get(email=email.lower()).username
user = authenticate(username=username, password=password)
login(request, user)

除了首先获取用户名之外,还有其他登录方式吗?

您应该编写一个自定义身份验证后端。类似这样的方法会奏效:

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend

class EmailBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        try:
            user = UserModel.objects.get(email=username)
        except UserModel.DoesNotExist:
            return None
        else:
            if user.check_password(password):
                return user
        return None
然后,在设置中将该后端设置为身份验证后端:

AUTHENTICATION_BACKENDS = ['path.to.auth.module.EmailBackend']
已更新。继承自
modelbend
,因为它已经实现了
get\u user()
等方法


请参阅此处的文档:

我有一个类似的要求,即用户名/电子邮件应适用于用户名字段。如果有人正在寻找验证后端方法,请查看以下工作代码。如果您只需要电子邮件,可以更改查询集

from django.contrib.auth import get_user_model  # gets the user_model django  default or your own custom
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q


# Class to permit the athentication using email or username
class CustomBackend(ModelBackend):  # requires to define two functions authenticate and get_user

    def authenticate(self, username=None, password=None, **kwargs):
        UserModel = get_user_model()

        try:
            # below line gives query set,you can change the queryset as per your requirement
            user = UserModel.objects.filter(
                Q(username__iexact=username) |
                Q(email__iexact=username)
            ).distinct()

        except UserModel.DoesNotExist:
            return None

        if user.exists():
            ''' get the user object from the underlying query set,
            there will only be one object since username and email
            should be unique fields in your models.'''
            user_obj = user.first()
            if user_obj.check_password(password):
                return user_obj
            return None
        else:
            return None

    def get_user(self, user_id):
        UserModel = get_user_model()
        try:
            return UserModel.objects.get(pk=user_id)
        except UserModel.DoesNotExist:
            return None

另外,在settings.py中添加AUTHENTICATION_BACKENDS=('path.to.CustomBackend',)您应该自定义ModelBackend类。
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import BaseBackend
from django.contrib.auth.hashers import check_password
from django.contrib.auth.models import User

class EmailBackend(BaseBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        try:
            user = UserModel.objects.get(email=username)
        except UserModel.DoesNotExist:
            return None
        else:
            if user.check_password(password):
                return user
        return None

    def get_user(self, user_id):
        UserModel = get_user_model()
        try:
            return UserModel.objects.get(pk=user_id)
        except UserModel.DoesNotExist:
            return None
我的简单代码:

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model

class YourBackend(ModelBackend):

  def authenticate(self, username=None, password=None, **kwargs):
    UserModel = get_user_model()
    if username is None:
        username = kwargs.get(UserModel.USERNAME_FIELD)
    try:
        if '@' in username:
            UserModel.USERNAME_FIELD = 'email'
        else:
            UserModel.USERNAME_FIELD = 'username'

        user = UserModel._default_manager.get_by_natural_key(username)
    except UserModel.DoesNotExist:
        UserModel().set_password(password)
    else:
        if user.check_password(password) and self.user_can_authenticate(user):
            return user
并在settings.py文件中添加:

AUTHENTICATION_BACKENDS = ['path.to.class.YourBackend']

如果您正在启动一个新项目,django强烈建议您设置一个自定义用户模型。(见附件)

如果您这样做了,请在您的用户模型中添加三行:

class MyUser(AbstractUser):
    USERNAME_FIELD = 'email'
    email = models.EmailField(_('email address'), unique=True) # changes email to unique and blank to false
    REQUIRED_FIELDS = [] # removes email from REQUIRED_FIELDS
然后
authenticate(电子邮件=电子邮件,密码=密码)
工作,而
authenticate(用户名=用户名,密码=密码)
停止工作

from django.contrib.auth.models import User

from django.db import Q

class EmailAuthenticate(object):

    def authenticate(self, username=None, password=None, **kwargs):
        try:
            user = User.objects.get(Q(email=username) | Q(username=username))
        except User.DoesNotExist:
            return None
        except MultipleObjectsReturned:
            return User.objects.filter(email=username).order_by('id').first()

        if user.check_password(password):
            return user
        return None

    def get_user(self,user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None
然后在
settings.py
中:

AUTHENTICATION_BACKENDS = (
  'articles.backends.EmailAuthenticate',
)
其中articles是我的django应用程序,
backends.py
是我应用程序中的python文件,
EmailAuthenticate
是django 2的
backends.py

文件中的身份验证后端类

username = get_object_or_404(User, email=data["email"]).username
        user = authenticate(
            request, 
            username = username, 
            password = data["password"]
        )
        login(request, user)
Django 2.x 正如Ganesh在上面提到的django 2.x,authenticate方法现在需要一个请求参数

# backends.py
from django.contrib.auth import backends, get_user_model
from django.db.models import Q
UserModel = get_user_model()


class ModelBackend(backends.ModelBackend):

    def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD)
        try:
            # user = UserModel._default_manager.get_by_natural_key(username)
            # You can customise what the given username is checked against, here I compare to both username and email fields of the User model
            user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
        except UserModel.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a nonexistent user (#20760).
            UserModel().set_password(password)
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user
        return super().authenticate(request, username, password, **kwargs)
将后端添加到项目设置中

# settings.py
AUTHENTICATION_BACKENDS = ['path.to.ModelBackend']
您的自定义用户模型需要使电子邮件对活动用户和验证用户具有唯一性。您只需使用以下方法即可做到这一点:

from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    objects = UserManager()
    email = models.EmailField(_('email address'), unique=True)

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')
        db_table = 'auth_user'
        swappable = 'AUTH_USER_MODEL'

但是为了防止有人阻止其他人使用他们的电子邮件,您应该添加电子邮件验证,并让您的注册和登录过程考虑到电子邮件可能不是唯一的(并且可能会阻止新用户使用现有和验证的电子邮件地址).Django 2.X的电子邮件和用户名验证

考虑到这是一个常见的问题,这里有一个自定义实现,它模拟了,但使用用户名或电子邮件对用户进行身份验证,不区分大小写,保留and

从django.contrib.auth.backends导入modelbend,UserModel
从django.db.models导入Q
类CustomBackend(ModelBackend):
def身份验证(self、request、username=None、password=None、**kwargs):
尝试:
user=UserModel.objects.get(Q(username\uuuiexact=username)| Q(email\uuuiexact=username))
除UserModel.DoesNotExist外:
UserModel().设置密码(password)
其他:
如果用户。检查密码(密码)和自我。用户\u可以\u身份验证(用户):
返回用户
def get_用户(自身,用户id):
尝试:
user=UserModel.objects.get(pk=user\u id)
除UserModel.DoesNotExist外:
一无所获
返回用户如果自己。用户\u可以\u身份验证(用户)否则无

始终记得将其添加到正确的设置中。

使用电子邮件和Django 2.x用户名进行身份验证

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
在settings.py中,添加以下行

AUTHENTICATION_BACKENDS = ['appname.filename.EmailorUsernameModelBackend']

Django 2.x的电子邮件身份验证

def admin_login(request):
if request.method == "POST":
    email = request.POST.get('email', None)
    password = request.POST.get('password', None)
    try:
        get_user_name = CustomUser.objects.get(email=email)
        user_logged_in =authenticate(username=get_user_name,password=password)
        if user_logged_in is not None:
            login(request, user_logged_in)
            messages.success(request, f"WelcomeBack{user_logged_in.username}")
            return HttpResponseRedirect(reverse('backend'))
        else:
            messages.error(request, 'Invalid Credentials')
            return HttpResponseRedirect(reverse('admin_login'))
    except:
        messages.warning(request, 'Wrong Email')
        return HttpResponseRedirect(reverse('admin_login'))

else:
    if request.user.is_authenticated:
        return HttpResponseRedirect(reverse('backend'))
    return render(request, 'login_panel/login.html')

Django 3.x的电子邮件身份验证

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
为了使用电子邮件/用户名和密码进行身份验证而不是默认的用户名和密码身份验证,我们需要重写ModelBackend类的两个方法:authenticate()和get_user():

get_user方法获取一个user_id–可以是用户名、数据库id或任何东西,,但必须是用户对象所独有的–并返回一个用户对象或无。如果您没有将电子邮件保留为唯一密钥,则必须处理查询集返回的多个结果。在下面的代码中,已通过从返回的列表返回第一个用户来处理此问题

from django.contrib.auth.backends import ModelBackend, UserModel
from django.db.models import Q

class EmailBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try: #to allow authentication through phone number or any other field, modify the below statement
            user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
        except UserModel.DoesNotExist:
            UserModel().set_password(password)
        except MultipleObjectsReturned:
            return User.objects.filter(email=username).order_by('id').first()
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user

    def get_user(self, user_id):
        try:
            user = UserModel.objects.get(pk=user_id)
        except UserModel.DoesNotExist:
            return None

        return user if self.user_can_authenticate(user) else None
默认情况下,身份验证\u后端设置为:

['django.contrib.auth.backends.ModelBackend']
在settings.py文件中,在底部添加以下内容以替代默认设置:

AUTHENTICATION_BACKENDS = ('appname.filename.EmailBackend',)

如果您创建了自定义数据库,如果您想验证您的电子邮件id和密码,请从该数据库开始

  • 使用
    models.objects.value\u list('db\u columnname').filter(db\u emailname=textbox Email)获取电子邮件id和密码
  • 2.在获取的列表中分配
    对象\u查询\u列表

    3.将列表转换为字符串

    例:

  • 获取
    Views.py中的Html
    Email\u id
    Password

    u\u email=request.POST.get('uemail')

    u\u pass=request.POST.get('upass')

  • 从数据库中获取电子邮件id和密码

    Email=B\u Reg.objects.values\u list('B\u Email',flat=True)。filter(B\u Email=u\u Email)

    Password=B\u Reg.objects.values\u list('Password',flat=True)。filter(B\u Email=u\u Email)

  • 查询
    值集中获取列表中的电子邮件id和密码值

    Email\u Value=Email[0]

    Password\u Value=Password[0]

  • 将列表转换为字符串

    string\u email=''.join(映射(str,email\u值))

    string\u password=''.join(映射(str,password\u值))

  • 最后你的罗
    # Create
    User.objects.create_user(username=post_data['email'] etc...)
    
    # Update
    user.username = post_data['email']
    user.save()
    
    # When you authenticate
    user = authenticate(username=post_data['email'], password=password)
    
    from django.contrib.auth import get_user_model
    from django.contrib.auth.backends import BaseBackend
    from django.contrib.auth.hashers import check_password
    from django.contrib.auth.models import User
    
    class EmailBackend(BaseBackend):
        def authenticate(self, request, username=None, password=None, **kwargs):
            UserModel = get_user_model()
            try:
                user = UserModel.objects.get(email=username)
            except UserModel.DoesNotExist:
                return None
            else:
                if user.check_password(password):
                    return user
            return None
    
        def get_user(self, user_id):
            UserModel = get_user_model()
            try:
                return UserModel.objects.get(pk=user_id)
            except UserModel.DoesNotExist:
                return None
    
    AUTHENTICATION_BACKENDS = (
        'appname.authentication.EmailBackend',
    )
    
    email = models.EmailField(_('email address'), blank=True,unique=True)
    
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']