
PythonEnthusiast
Ich möchte, dass Django Benutzer per E-Mail authentifiziert, nicht über Benutzernamen. Eine Möglichkeit besteht darin, den E-Mail-Wert als Benutzernamenwert bereitzustellen, aber das möchte ich nicht. Der Grund dafür ist, dass ich eine URL habe /profile/<username>/
daher kann ich keine URL haben /profile/[email protected]/
.
Ein weiterer Grund ist, dass alle E-Mails einzigartig sind, aber manchmal kommt es vor, dass der Benutzername bereits vergeben ist. Daher erstelle ich den Benutzernamen automatisch als fullName_ID
.
Wie kann ich einfach ändern, dass Django sich mit E-Mail authentifiziert?
So erstelle ich einen Benutzer.
username = `abcd28`
user_email = `[email protected]`
user = User.objects.create_user(username, user_email, user_pass)
So melde ich mich an.
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)
Gibt es eine andere Möglichkeit, sich anzumelden, außer zuerst den Benutzernamen zu erhalten?

mipadi
Sie sollten ein benutzerdefiniertes Authentifizierungs-Backend schreiben. So etwas wird funktionieren:
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
Legen Sie dann dieses Backend in Ihren Einstellungen als Ihr Authentifizierungs-Backend fest:
AUTHENTICATION_BACKENDS = ['path.to.auth.module.EmailBackend']
Aktualisiert. Geerbt von ModelBackend
da es Methoden wie implementiert get_user()
schon.
Siehe Dokumente hier: https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#writing-an-authentication-backend

Nikolaus
Wenn Sie ein neues Projekt starten, hat Django Ihnen dringend empfohlen, ein benutzerdefiniertes Benutzermodell einzurichten. (sehen https://docs.djangoproject.com/en/dev/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project)
und wenn Sie es getan haben, fügen Sie Ihrem Benutzermodell drei Zeilen hinzu:
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
Dann authenticate(email=email, password=password)
funktioniert, während authenticate(username=username, password=password)
hört auf zu arbeiten.

Himanshu Singh
E-Mail-Authentifizierung für Django 3.x
Um E-Mail/Benutzername und Passwort für die Authentifizierung anstelle der standardmäßigen Benutzernamen- und Passwortauthentifizierung zu verwenden, müssen wir zwei Methoden der ModelBackend-Klasse überschreiben: authenticate() und get_user():
Die get_user-Methode nimmt eine user_id – die ein Benutzername, eine Datenbank-ID oder was auch immer sein könnte, muss aber für Ihr Benutzerobjekt eindeutig sein – und gibt ein Benutzerobjekt oder None zurück. Wenn Sie E-Mail nicht als eindeutigen Schlüssel gespeichert haben, müssen Sie sich um mehrere Ergebnisse kümmern, die für das query_set zurückgegeben werden. Im folgenden Code wurde dies erledigt, indem der erste Benutzer aus der zurückgegebenen Liste zurückgegeben wurde.
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
Standardmäßig ist AUTHENTICATION_BACKENDS eingestellt auf:
['django.contrib.auth.backends.ModelBackend']
Fügen Sie in der Datei settings.py unten Folgendes hinzu, um die Standardeinstellung zu überschreiben:
AUTHENTICATION_BACKENDS = ('appname.filename.EmailBackend',)

Bob
Django 4.0
Es gibt zwei Möglichkeiten, die E-Mail-Authentifizierung zu implementieren, wobei Folgendes zu beachten ist:
- E-Mails sollten nicht in einem Benutzermodell eindeutig sein, um Rechtschreibfehler und böswillige Verwendung zu verhindern.
- E-Mails sollten nur dann zur Authentifizierung verwendet werden, wenn dies der Fall ist verifiziert (wie in Wir haben eine Bestätigungs-E-Mail gesendet und sie haben auf den Bestätigungslink geklickt).
- Wir sollten nur E-Mails senden an verifiziert E-mailadressen.
Benutzerdefiniertes Benutzermodell
Ein benutzerdefiniertes Benutzermodell ist empfohlen beim Starten eines neuen Projekts, da das Wechseln in der Mitte des Projekts schwierig sein kann.
Wir werden ein hinzufügen email_verified
Feld, um die E-Mail-Authentifizierung auf Benutzer mit einer verifizierten E-Mail-Adresse zu beschränken.
# app.models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
email_verified = models.BooleanField(default=False)
Wir werden dann ein benutzerdefiniertes Authentifizierungs-Backend erstellen, das eine bestimmte E-Mail-Adresse durch einen Benutzernamen ersetzt.
Dieses Backend funktioniert mit Authentifizierungsformularen, die explizit eine festlegen email
Feld sowie die Einstellung a username
aufstellen.
# app.backends.py
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
UserModel = get_user_model()
class CustomUserModelBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD, kwargs.get(UserModel.EMAIL_FIELD))
if username is None or password is None:
return
try:
user = UserModel._default_manager.get(
Q(username__exact=username) | (Q(email__iexact=username) & Q(email_verified=True))
)
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
Wir ändern dann unsere Projekte settings.py
um unser benutzerdefiniertes Benutzermodell und Authentifizierungs-Backend zu verwenden.
# project.settings.py
AUTH_USER_MODEL = "app.User"
AUTHENTICATION_BACKENDS = ["app.backends.CustomUserModelBackend"]
Stellen Sie sicher, dass Sie laufen manage.py makemigrations
bevor du migrate
und dass die erste Migration diese Einstellungen enthält.
Erweitertes Benutzermodell
Obwohl weniger leistungsfähig als ein Custom User
Modell (erfordert eine sekundäre Abfrage), ist es möglicherweise besser erweitern die bestehende User
Modell in einem bestehenden Projekt und kann je nach Anmeldefluss und Verifizierungsprozess bevorzugt werden.
Wir schaffen eine Eins-zu-eins-Beziehung aus EmailVerification
zu welchem auch immer User
Modell, das unser Projekt verwendet, durch die AUTH_USER_MODEL
Einstellung.
# app.models.py
from django.conf import settings
from django.db import models
class EmailVerification(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_query_name="verification"
)
verified = models.BooleanField(default=False)
Wir können auch einen benutzerdefinierten Admin erstellen, der unsere Erweiterung inline enthält.
# app.admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .models import EmailVerification
UserModel = get_user_model()
class VerificationInline(admin.StackedInline):
model = EmailVerification
can_delete = False
verbose_name_plural="verification"
class UserAdmin(BaseUserAdmin):
inlines = (VerificationInline,)
admin.site.unregister(UserModel)
admin.site.register(UserModel, UserAdmin)
Wir erstellen dann ein Backend ähnlich dem obigen, das einfach die zugehörigen Modelle überprüft verified
aufstellen.
# app.backends.py
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
UserModel = get_user_model()
class ExtendedUserModelBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD, kwargs.get(UserModel.EMAIL_FIELD))
if username is None or password is None:
return
try:
user = UserModel._default_manager.get(
Q(username__exact=username) | (Q(email__iexact=username) & Q(verification__verified=True))
)
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
Wir ändern dann unsere Projekte settings.py
um unser Authentifizierungs-Backend zu verwenden.
# project.settings.py
AUTHENTICATION_BACKENDS = ["app.backends.ExtendedUserModelBackend"]
Sie können dann makemigrations
und migrate
um Funktionalität zu einem bestehenden Projekt hinzuzufügen.
Anmerkungen
- wenn bei Benutzernamen die Groß-/Kleinschreibung nicht beachtet wird, ändern
Q(username__exact=username)
zu Q(username__iexact=username)
.
- In der Produktion verhindern, dass sich ein neuer Benutzer mit einer vorhandenen verifizierten E-Mail-Adresse registriert.

anuragb26
Ich hatte eine ähnliche Anforderung, bei der entweder Benutzername/E-Mail für das Benutzernamenfeld funktionieren sollte. Falls jemand nach der Authentifizierungs-Backend-Methode dafür sucht, sehen Sie sich den folgenden Arbeitscode an. Sie können den Abfragesatz ändern, wenn Sie nur die E-Mail wünschen.
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
Fügen Sie außerdem AUTHENTICATION_BACKENDS = ( ‘path.to.CustomBackend’, ) in settings.py hinzu
E-Mail- und Benutzernamen-Authentifizierung für Django 2.X
In Anbetracht dessen, dass dies eine häufige Frage ist, ist hier eine benutzerdefinierte Implementierung, die die nachahmt Django-Quellcode aber das authentifiziert den Benutzer entweder mit Benutzername oder E-Mail, ohne Berücksichtigung der Groß- und Kleinschreibung, wobei die Timing-Angriff Schutz und inaktive Benutzer werden nicht authentifiziert.
from django.contrib.auth.backends import ModelBackend, UserModel
from django.db.models import Q
class CustomBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
try:
user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
except UserModel.DoesNotExist:
UserModel().set_password(password)
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
Denken Sie immer daran, Ihrer settings.py die richtige hinzuzufügen Authentifizierungs-Backend.

bitFez
Es scheint, dass die Methode dazu mit Django 3.0 aktualisiert wurde.
Eine Arbeitsmethode für mich war:
authentication.py # <-- Ich habe dies in einer App platziert (funktionierte nicht im Projektordner neben settings.py
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
Fügen Sie dies dann der Datei settings.py hinzu
AUTHENTICATION_BACKENDS = (
'appname.authentication.EmailBackend',
)
10152100cookie-checkDjango – Login mit E-Mailyes