6 Stimmen

E-Mail anstelle des Anmeldenamens in django verwenden

Erstens geht es hier nicht um die Frage, wie man sich mit einem E-Mail/Passwort-Paar authentifizieren kann, sondern vielmehr darum, wie man eine logische und, wenn Sie so wollen, schöne Datenstruktur erzeugt.

Ich möchte E-Mails als Benutzernamen in einem bestimmten Django-Projekt zu verwenden. Allerdings bin ich nicht in der Lage, Felder wiederverwenden, die von auth.User Modell aus mindestens zwei Gründen:

  1. Das Feld max_length von auth.User.username hat eine Länge von 30 Zeichen, was für einige E-Mail-Adressen möglicherweise nicht ausreicht.

  2. auth.User.email ist nicht eindeutig - das ist offensichtlich nicht zufriedenstellend für eine Voraussetzung, die besagt, dass Benutzernamen eindeutig sein müssen.

Ein naheliegender Weg ist hier also, den Benutzernamen in einem benutzerdefinierten Profil zu speichern, das mit auth.User verknüpft ist. In diesem Fall müssen wir mit folgenden Problemen umgehen:

  1. Eindeutigen Benutzernamen für auth.User.username generieren - md5-Hash der E-Mail sollte hier ausreichen?
  2. Lassen Sie auth.User.email komplett leer - da es nur 75 Zeichen lang ist, während laut RFC 5321 ( Wie lang darf eine gültige E-Mail-Adresse maximal sein? ) E-Mail kann bis zu 256 Zeichen lang sein.

Die folgende Problematik ergibt sich aus der vorgeschlagenen Lösung:

  1. Es ist nicht möglich, integrierte Ansichten/Vorlagen für Standardvorgänge wie das Zurücksetzen von Passwörtern usw. wiederzuverwenden.
  2. Im Falle einer E-Mail-Änderung muss auth.User.username aktualisiert werden

Um noch Öl ins Feuer zu gießen, ist es unwahrscheinlich, dass die Django-Entwickler diese Einschränkung in absehbarer Zeit beheben werden - siehe http://code.djangoproject.com/ticket/11365

Die Frage ist also: Gibt es eine andere Möglichkeit, dies zu tun, und sehen Sie irgendwelche anderen Nachteile in der oben vorgeschlagenen Lösung?

Merci !

0voto

Adrian Lopez Punkte 2271

Ich habe eine Lösung auf der Grundlage der Antwort von Dominique geschrieben, die Sicherheitsverbesserungen und einige zusätzliche Funktionen wie die Authentifizierung unter Berücksichtigung der Groß-/Kleinschreibung enthält. Wenn Sie es bevorzugen, können Sie Installieren Sie es direkt von pypi :

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

###################################
"""  DEFAULT SETTINGS + ALIAS   """
###################################

try:
    am = settings.AUTHENTICATION_METHOD
except:
    am = 'both'
try:
    cs = settings.AUTHENTICATION_CASE_SENSITIVE
except:
    cs = 'both'

#####################
"""   EXCEPTIONS  """
#####################

VALID_AM = ['username', 'email', 'both']
VALID_CS = ['username', 'email', 'both', 'none']

if (am not in VALID_AM):
    raise Exception("Invalid value for AUTHENTICATION_METHOD in project "
                    "settings. Use 'username','email', or 'both'.")

if (cs not in VALID_CS):
    raise Exception("Invalid value for AUTHENTICATION_CASE_SENSITIVE in project "
                    "settings. Use 'username','email', 'both' or 'none'.")

############################
"""  OVERRIDDEN METHODS  """
############################

class DualAuthentication(ModelBackend):
    """
    This is a ModelBacked that allows authentication
    with either a username or an email address.
    """

    def authenticate(self, username=None, password=None):
        UserModel = get_user_model()
        try:
            if ((am == 'email') or (am == 'both')):
                if ((cs == 'email') or cs == 'both'):
                    kwargs = {'email': username}
                else:
                    kwargs = {'email__iexact': username}

                user = UserModel.objects.get(**kwargs)
            else:
                raise
        except:
            if ((am == 'username') or (am == 'both')):
                if ((cs == 'username') or cs == 'both'):
                    kwargs = {'username': username}
                else:
                kwargs = {'username__iexact': username}

                user = UserModel.objects.get(**kwargs)
        finally:
            try:
                if user.check_password(password):
                    return user
            except:
                # Run the default password hasher once to reduce the timing
                # difference between an existing and a non-existing user.
                UserModel().set_password(password)
                return None

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

0voto

evergreen Punkte 6951

Für beide Authentifizierungen [Benutzername, E-Mail] ohne Änderungsmodelle einfach Backend hinzufügen:

methode beide authentifizierung [email, benutzername]

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X