Ich möchte, dass Django Benutzer per E-Mail und nicht über Benutzernamen authentifiziert. Eine Möglichkeit kann darin bestehen, einen E-Mail-Wert als Benutzernamenwert anzugeben, aber das möchte ich nicht. 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 eindeutig sind, aber manchmal wird der Benutzername bereits vergeben. Daher erstelle ich den Benutzernamen automatisch als fullName_ID
.
Wie kann ich einfach ändern, damit sich Django per 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 logge ich mich ein.
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, als zuerst den Benutzernamen zu erhalten?
if user.check_password(password):
möchten, möchten Sie wahrscheinlich angeben, was Django standardmäßig überModelBackend
: tut,if user.check_password(password) and self.user_can_authenticate(user):
um zu überprüfen, ob der Benutzer dies hatis_active=True
.Wenn Sie ein neues Projekt starten, hat django Ihnen dringend empfohlen, ein benutzerdefiniertes Benutzermodell einzurichten. (Siehe https://docs.djangoproject.com/de/dev/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project )
Wenn Sie dies 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
Funktioniert dann
authenticate(email=email, password=password)
, während es nicht mehrauthenticate(username=username, password=password)
funktioniert.quelle
class MyUserManager(BaseUserManager): def create_superuser(self, email, password, **kwargs): user = self.model(email=email, is_staff=True, is_superuser=True, **kwargs) user.set_password(password) user.save() return user
Ich hatte eine ähnliche Anforderung, bei der entweder Benutzername / E-Mail für das Feld Benutzername funktionieren sollte. Wenn jemand nach der Authentifizierungs-Backend-Methode sucht, lesen Sie den folgenden Arbeitscode. 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
quelle
E-Mail-Authentifizierung für Django 3.x.
Um E-Mail / Benutzername und Kennwort für die Authentifizierung anstelle der Standardauthentifizierung für Benutzername und Kennwort zu verwenden, müssen zwei Methoden der ModelBackend-Klasse überschrieben werden: authenticate () und get_user ():
Die Methode get_user verwendet eine Benutzer-ID, die ein Benutzername, eine Datenbank-ID oder was auch immer sein kann, aber für Ihr Benutzerobjekt eindeutig sein muss, und gibt ein Benutzerobjekt oder Keine 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 behoben, 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 auf Folgendes festgelegt:
['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',)
quelle
Django 2.x.
Wie von Ganesh oben für django 2.x erwähnt, erfordert die Authentifizierungsmethode jetzt einen Anforderungsparameter.
# 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)
Fügen Sie Ihr Backend zu Ihren Projekteinstellungen hinzu
# settings.py AUTHENTICATION_BACKENDS = ['path.to.ModelBackend']
Ihr benutzerdefiniertes Benutzermodell muss E-Mails für aktive und validierte Benutzer eindeutig machen. Sie können dies einfach mit folgenden Schritten tun:
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'
Um jedoch zu verhindern, dass jemand andere daran hindert, seine E-Mails zu verwenden, sollten Sie stattdessen eine E-Mail-Validierung hinzufügen und bei Ihrem Registrierungs- und Anmeldevorgang berücksichtigen, dass E-Mails möglicherweise nicht eindeutig sind (und wahrscheinlich verhindern, dass neue Benutzer eine vorhandene und validierte E-Mail-Adresse verwenden).
quelle
E-Mail- und Benutzernamenauthentifizierung für Django 2.X.
In Anbetracht dessen, dass dies eine häufig gestellte Frage ist, handelt es sich um eine benutzerdefinierte Implementierung, die den Django-Quellcode nachahmt , den Benutzer jedoch entweder mit Benutzername oder E-Mail authentifiziert, wobei die Groß- und Kleinschreibung nicht berücksichtigt wird, der Schutz vor Timing-Angriffen beibehalten wird und inaktive Benutzer nicht authentifiziert werden .
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, Ihre Einstellungen hinzuzufügen. Geben Sie das richtige Authentifizierungs-Backend ein .
quelle
UserModel().set_password(password)
dass Angreifer verhindern können, dass festgestellt wird, ob ein Benutzer existiert oder nicht, indem sie unabhängig davon ungefähr die gleiche Menge an kryptografischer Arbeit ausführen (ich gehe davon aus, dass dies der von Ihnen beabsichtigte Timing-Angriff ist)?Sie sollten die ModelBackend-Klasse anpassen. Mein einfacher Code:
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
Fügen Sie in der Datei settings.py Folgendes hinzu:
AUTHENTICATION_BACKENDS = ['path.to.class.YourBackend']
quelle
request
Parameter inauthenticate
Methode für Django 2.1.1Authentifizierung mit E-Mail und Benutzername für 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
Fügen Sie in settings.py die folgende Zeile hinzu:
AUTHENTICATION_BACKENDS = ['appname.filename.EmailorUsernameModelBackend']
quelle
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
Und dann in
settings.py
:Dabei ist Artikel meine Django-App,
backends.py
die Python-Datei in meiner App undEmailAuthenticate
die Authentifizierungs-Backend-Klasse in meinerbackends.py
Dateiquelle
Ziemlich einfach. Es sind keine zusätzlichen Klassen erforderlich.
Wenn Sie einen Benutzer mit einer E-Mail erstellen und aktualisieren, legen Sie einfach das Feld Benutzername mit der E-Mail fest.
Wenn Sie das Feld Benutzername authentifizieren, entspricht dies dem Wert der E-Mail.
Der Code:
# 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)
quelle
Für Django 2
username = get_object_or_404(User, email=data["email"]).username user = authenticate( request, username = username, password = data["password"] ) login(request, user)
quelle
Authentifizierung mit E-Mail für 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')
quelle
Wenn Sie eine benutzerdefinierte Datenbank erstellt haben, können Sie von dort aus Ihre E-Mail-ID und Ihr Kennwort überprüfen.
models.objects.value_list('db_columnname').filter(db_emailname=textbox email)
2. In der abgerufenen Liste zuordnen
object_query_list
3. Konvertieren Sie die Liste in einen String
Ex :
Nehmen Sie das HTML
Email_id
und diePassword
Werte inViews.py
u_email = request.POST.get('uemail')
u_pass = request.POST.get('upass')
Rufen Sie die E-Mail-ID und das Kennwort aus der Datenbank ab
Email = B_Reg.objects.values_list('B_Email',flat=True).filter(B_Email=u_email)
Password = B_Reg.objects.values_list('Password',flat=True).filter(B_Email=u_email)
Nehmen Sie die Werte für E-Mail-ID und Kennwort in der Liste aus dem eingestellten
Query
WertEmail_Value = Email[0]
Password_Value=Password[0]
Liste in String konvertieren
string_email = ''.join(map(str, Email_Value))
string_password = ''.join(map(str, Password_Value))
Endlich Ihre Login-Bedingung
if (string_email==u_email and string_password ==u_pass)
quelle
Ich habe einen Helfer dafür erstellt: Funktion
authenticate_user(email, password)
.from django.contrib.auth.models import User def authenticate_user(email, password): try: user = User.objects.get(email=email) except User.DoesNotExist: return None else: if user.check_password(password): return user return None class LoginView(View): template_name = 'myapp/login.html' def get(self, request): return render(request, self.template_name) def post(self, request): email = request.POST['email'] password = request.POST['password'] user = authenticate_user(email, password) context = {} if user is not None: if user.is_active: login(request, user) return redirect(self.request.GET.get('next', '/')) else: context['error_message'] = "user is not active" else: context['error_message'] = "email or password not correct" return render(request, self.template_name, context)
quelle
Es scheint, dass die Methode dazu mit Django 3.0 aktualisiert wurde.
Eine Arbeitsmethode für mich war:
authentication.py # <- Ich habe dies in eine App eingefügt (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
quelle