Ich hoffe, Sie können mir helfen, den besten Weg zu finden, um eine manuelle (serverseitig initiierte) Anmeldung ohne Verwendung des Kennworts zu implementieren . Lassen Sie mich den Workflow erklären:
- Benutzerregister
- Vielen Dank! Eine E-Mail mit einem Aktivierungslink wurde blablabla gesendet
- (Konto existiert jetzt, ist aber als nicht aktiviert markiert)
- Benutzer öffnet E-Mail, klickt auf Link
- (Konto ist aktiviert)
- Vielen Dank! Sie können die Site jetzt verwenden
Ich versuche, den Benutzer anzumelden, nachdem er auf den E-Mail-Link geklickt hat, damit er die Website sofort nutzen kann.
Ich kann sein Kennwort nicht verwenden, da es in der Datenbank verschlüsselt ist. Ist die einzige Option, ein benutzerdefiniertes Authentifizierungs-Backend zu schreiben?
Antworten:
Sie benötigen kein Kennwort, um einen Benutzer anzumelden. Die
auth.login
Funktion nimmt nur einUser
Objekt entgegen, das Sie vermutlich bereits aus der Datenbank erhalten, wenn Sie das Konto aktivieren. Sie können das also direkt an weitergebenlogin
.Natürlich müssen Sie sehr vorsichtig sein, dass ein Benutzer auf keinen Fall einen Link zu einem bereits aktivierten Konto fälschen kann, der ihn dann automatisch als diesen Benutzer anmeldet.
from django.contrib.auth import login def activate_account(request, hash): account = get_account_from_hash(hash) if not account.is_active: account.activate() account.save() user = account.user login(request, user)
... etc.
Bearbeitet :
Hmm, habe diese Anforderung
authenticate
wegen der zusätzlichen Eigenschaft, die sie hinzufügt , nicht bemerkt . Wenn Sie sich den Code ansehen, ist alles, was er tut, einbackend
Attribut, das dem Modulpfad des authentifizierenden Backends entspricht. Sie können es also einfach vortäuschen - tun Sie dies vor dem obigen Login-Aufruf:user.backend = 'django.contrib.auth.backends.ModelBackend'
quelle
backend
Einstellung tatsächlich in der Liste enthalten ist,AUTHENTICATION_BACKENDS
damit sie funktioniert.Ab Django 1.10 wurde der Prozess vereinfacht.
In allen Versionen von Django muss ein Benutzer, damit er angemeldet sein kann, von einem der Backends Ihrer App authentifiziert werden (gesteuert durch die
AUTHENTICATION_BACKENDS
Einstellung).Wenn Sie einfach eine Anmeldung erzwingen möchten, können Sie einfach behaupten, dass der Benutzer vom ersten Backend aus dieser Liste authentifiziert wurde:
from django.conf import settings from django.contrib.auth import login # Django 1.10+ login(request, user, backend=settings.AUTHENTICATION_BACKENDS[0]) # Django <1.10 - fake the authenticate() call user.backend = settings.AUTHENTICATION_BACKENDS[0] login(request, user)
quelle
login(request, user, backend=settings.AUTHENTICATION_BACKENDS[0])
Daniels Antwort ist sehr gut.
Eine andere Möglichkeit besteht darin, ein HashModelBackend nach dem Backend für benutzerdefinierte Autorisierung zu erstellen : https://docs.djangoproject.com/de/1.8/topics/auth/customizing/#writing-an-authentication-backend wie folgt :
class HashModelBackend(object): def authenticate(self, hash=None): user = get_user_from_hash(hash) return user def get_user(self, user_id): try: return User.objects.get(pk=user_id) except User.DoesNotExist: return None
Und dann installieren Sie dies in Ihren Einstellungen:
Dann wäre Ihre Ansicht ungefähr so:
def activate_account(request, hash): user = authenticate(hash=hash) if user: # check if user is_active, and any other checks login(request, user) else: return user_not_found_bad_hash_message
quelle
Antwort auf Dans Antwort.
Eine Möglichkeit, Ihr Backend zu schreiben:
from django.contrib.auth import get_user_model from django.contrib.auth.backends import ModelBackend class HashModelBackend(ModelBackend): def authenticate(self, username=None, **kwargs): UserModel = get_user_model() if username is None: username = kwargs.get(UserModel.USERNAME_FIELD) try: user = UserModel._default_manager.get_by_natural_key(username) return user except UserModel.DoesNotExist: return None
Die Antwort basiert auf dem Quellcode django.contrib.auth.backends.ModelBackend . Es ist aktuell für Django 1.9
Und ich würde lieber ein benutzerdefiniertes Backend unter die Standardeinstellung von Django stellen:
AUTHENTICATION_BACKENDS = [ 'django.contrib.auth.backends.ModelBackend', 'yours.HashModelBackend', ]
weil die Kontoaktivierung weniger möglich ist als die Anmeldung selbst. Laut https://docs.djangoproject.com/de/1.9/topics/auth/customizing/#specifying-authentication-backends :
Seien Sie vorsichtig, dieser Code authentifiziert Ihre Benutzer auch mit falschen Passwörtern.
quelle
Sie können ein
ska
Paket verwenden, für das eine kennwortlose Anmeldung bei Django implementiert ist.ska
arbeitet mit Authentifizierungstoken und seine Sicherheit basiert auf SHARED_KEY, das für alle beteiligten Parteien (Server) gleich sein sollte.Auf der Clientseite (Partei, die eine kennwortlose Anmeldung anfordert) generieren Sie eine URL und signieren sie mit
ska
. Beispiel:from ska import sign_url from ska.contrib.django.ska.settings import SECRET_KEY server_ska_login_url = 'https://server-url.com/ska/login/' signed_url = sign_url( auth_user='test_ska_user_0', secret_key=SECRET_KEY, url=server_ska_login_url extra={ 'email': '[email protected]', 'first_name': 'John', 'last_name': 'Doe', } )
Die Standardlebensdauer des Tokens beträgt 600 Sekunden. Sie können dies anpassen, indem Sie ein
lifetime
Argument beweisen .Auf der Serverseite (Site, bei der sich Benutzer anmelden) wird
ska
der Benutzer beim ordnungsgemäßen Installieren beim Aufrufen der URL angemeldet, sofern vorhanden (Benutzername-Übereinstimmung) oder auf andere Weise erstellt. Es gibt 3 Rückrufe, die Sie in den Django-Einstellungen Ihres Projekts anpassen können.USER_GET_CALLBACK
(Zeichenfolge): Wird ausgelöst, wenn der Benutzer erfolgreich aus der Datenbank abgerufen wurde (vorhandener Benutzer).USER_CREATE_CALLBACK
(Zeichenfolge): Wird direkt nach dem Erstellen des Benutzers ausgelöst (Benutzer war nicht vorhanden).USER_INFO_CALLBACK
(Zeichenfolge): Wird bei erfolgreicher Authentifizierung ausgelöst.Weitere Informationen finden Sie in der Dokumentation ( http://pythonhosted.org/ska/ ).
quelle