Wie kann eine RESTful-Ressource zum Zurücksetzen eines Kennworts richtig strukturiert werden?
Diese Ressource ist als Passwort-Resetter für jemanden gedacht, der sein Passwort verloren oder vergessen hat. Es macht ihr altes Passwort ungültig und sendet ihnen ein Passwort per E-Mail.
Die zwei Optionen, die ich habe, sind:
POST /reset_password/{user_name}
oder...
POST /reset_password
-Username passed through request body
Ich bin mir ziemlich sicher, dass die Anfrage ein POST sein sollte. Ich bin weniger sicher, dass ich einen geeigneten Namen ausgewählt habe. Und ich bin nicht sicher, ob der Benutzername über die URL oder den Anfragetext übergeben werden soll.
quelle
Nicht authentifizierte Benutzer
Wir führen eine
PUT
Anfrage auf einemapi/v1/account/password
Endpunkt durch und benötigen einen Parameter mit der entsprechenden Konto-E-Mail, um das Konto zu identifizieren, für das der Benutzer das Kennwort zurücksetzen (aktualisieren) möchte:Hinweis: Wie @DougDomeny in seinem Kommentar erwähnt hat, ist das Übergeben der E-Mail als Abfragezeichenfolge in der URL ein Sicherheitsrisiko. GET-Parameter werden bei der Verwendung nicht angezeigt
https
(und Sie solltenhttps
für solche Anforderungen immer eine ordnungsgemäße Verbindung verwenden), es bestehen jedoch andere Sicherheitsrisiken. Weitere Informationen zu diesem Thema finden Sie in diesem Blogbeitrag hier .Das Übergeben der E-Mail im Anforderungshauptteil wäre eine sicherere Alternative zum Übergeben als GET-Parameter:
Text anfordern:
Die Antwort hat eine
202
akzeptierte Antwortbedeutung:Der Benutzer erhält eine E-Mail an
[email protected]
und die Verarbeitung der Aktualisierungsanforderung hängt von den Aktionen ab, die mit dem Link aus der E-Mail ausgeführt werden.Das Öffnen des Links aus dieser E-Mail führt zu einem Formular zum Zurücksetzen des Kennworts in der Front-End-Anwendung, das das Token zum Zurücksetzen des Kennworts vom Link als Eingabe für ein verstecktes Eingabefeld verwendet (das Token ist Teil des Links als Abfragezeichenfolge). In einem weiteren Eingabefeld kann der Benutzer ein neues Passwort festlegen. Eine zweite Eingabe zur Bestätigung des neuen Passworts wird zur Validierung im Front-End verwendet (um Tippfehler zu vermeiden).
Hinweis: In der E-Mail können wir auch erwähnen, dass der Benutzer, falls er kein Zurücksetzen des Passworts initialisiert hat, die E-Mail ignorieren und die Anwendung weiterhin normal mit seinem aktuellen Passwort verwenden kann
Wenn das Formular mit dem neuen Passwort und dem Token als Eingabe gesendet wird, findet der Vorgang zum Zurücksetzen des Passworts statt. Die Formulardaten werden erneut mit einer
PUT
Anfrage gesendet, diesmal jedoch einschließlich des Tokens, und wir ersetzen das Ressourcenkennwort durch einen neuen Wert:Text anfordern:
Die Antwort ist eine Antwort
204
ohne InhaltAuthentifizierte Benutzer
Für authentifizierte Benutzer, die ihr Passwort ändern möchten,
PUT
kann die Anforderung sofort ohne E-Mail ausgeführt werden (das Konto, für das wir das Passwort aktualisieren, ist dem Server bekannt). In diesem Fall sendet das Formular zwei Felder:Text anfordern:
quelle
Lassen Sie uns für eine Sekunde überruhig werden. Warum nicht die Aktion DELETE für das Passwort verwenden, um einen Reset auszulösen? Macht Sinn, nicht wahr? Schließlich verwerfen Sie das vorhandene Passwort effektiv zugunsten eines anderen.
Das heißt, Sie würden tun:
Nun zwei große Vorbehalte:
HTTP DELETE soll idempotent sein (ein schickes Wort für "keine große Sache, wenn Sie es mehrmals tun"). Wenn Sie die üblichen Aufgaben wie das Versenden einer E-Mail mit dem Titel "Passwort zurücksetzen" ausführen, treten Probleme auf. Sie könnten dies umgehen, indem Sie den Benutzer / das Kennwort mit einem booleschen "Is Reset" -Flag versehen. Bei jedem Löschen aktivieren Sie dieses Flag. Wenn es nicht festgelegt ist , können Sie das Passwort zurücksetzen und Ihre E-Mail senden. (Beachten Sie, dass dieses Flag auch andere Verwendungszwecke haben kann.)
Sie können HTTP DELETE nicht über ein Formular verwenden , daher müssen Sie einen AJAX-Aufruf tätigen und / oder das DELETE über den POST tunneln.
quelle
DELETE
gute Passform. Sie würden das Passwort durch ein zufällig generiertes ersetzen,DELETE
könnte also irreführend sein. Ich bevorzuge dieCreate (POST) new reset_password action
, bei der das Substantiv (Ressource), auf das Sie einwirken würden, die "reset_password action" ist. Dies eignet sich auch gut zum Senden von E-Mails, da die Aktion alle diese Details auf niedrigerer Ebene enthält.POST
ist nicht idempotent.Oft möchten Sie das vorhandene Kennwort des Benutzers bei der ersten Anforderung nicht löschen oder zerstören, da dies möglicherweise (unbeabsichtigt oder absichtlich) von einem Benutzer ausgelöst wurde, der keinen Zugriff auf die E-Mail hat. Aktualisieren Sie stattdessen ein Reset-Kennwort-Token im Benutzerdatensatz und senden Sie es über einen in einer E-Mail enthaltenen Link. Durch Klicken auf den Link wird bestätigt, dass der Benutzer das Token erhalten hat und sein Kennwort aktualisieren möchte. Im Idealfall wäre dies auch zeitkritisch.
Die RESTful-Aktion wäre in diesem Fall ein POST: Auslösen der Erstellungsaktion auf dem PasswordResets-Controller. Die Aktion selbst würde das Token aktualisieren und eine E-Mail senden.
quelle
Ich suche tatsächlich nach einer Antwort, ohne eine zu liefern - aber "reset_password" klingt für mich in einem REST-Kontext falsch, weil es ein Verb ist, kein Substantiv. Selbst wenn Sie sagen, dass Sie ein Substantiv "Aktion zurücksetzen" ausführen - mit dieser Begründung sind alle Verben Substantive.
Es ist möglicherweise auch niemandem in den Sinn gekommen, nach der gleichen Antwort zu suchen, dass Sie den Benutzernamen möglicherweise über den Sicherheitskontext abrufen können und ihn überhaupt nicht über die URL oder den Text senden müssen, was mich nervös macht.
quelle
reset-password
wie ein Verb, aber Sie können es leicht umkehren (password-reset
), um es zu einem Substantiv zu machen. Und wenn Sie Ihre Anwendung mithilfe von Event Sourcing modelliert haben oder nur eine Art von Prüfung haben, ist es sinnvoll, dass Sie tatsächlich eine echte Entität mit diesem Namen haben und möglicherweise sogar GETs darauf zulassen, die Benutzer oder Administratoren sehen können Verlauf (offensichtlich Maskierung des Passworttextes). Macht mich überhaupt nicht nervös. Und was das automatische Abrufen des Benutzernamens auf der Serverseite betrifft - Sie können, aber wie gehen Sie dann mit Dingen wie Verwaltung / Identitätswechsel um?reset-password
gelingt mir, die Auswirkungen gut zu beschreiben.Ich denke, eine bessere Idee wäre:
In Bezug auf die Bereitstellung der Daten:
Aktuelles Passwort zurücksetzen
So erstellen Sie ein neues Passwort (nach dem Zurücksetzen)
So aktualisieren Sie das Kennwort (für angemeldete Benutzer)
quelle
Es sind einige Überlegungen zu treffen:
Das Zurücksetzen von Passwörtern ist nicht idempotent
Eine Kennwortänderung wirkt sich auf die Daten aus, die als Anmeldeinformationen für die Ausführung verwendet werden. Dies kann zukünftige Versuche ungültig machen, wenn die Anforderung einfach wörtlich wiederholt wird, während sich die gespeicherten Anmeldeinformationen geändert haben. Wenn beispielsweise ein Token zum vorübergehenden Zurücksetzen verwendet wird, um die Änderung zuzulassen, wie es in einer Situation mit vergessenem Kennwort üblich ist, sollte dieses Token bei erfolgreicher Kennwortänderung abgelaufen sein, wodurch weitere Versuche, die Anforderung zu replizieren, erneut zunichte gemacht werden. Daher scheint ein RESTful-Ansatz für eine Kennwortänderung ein Job zu sein, der besser geeignet ist
POST
alsPUT
.ID oder E-Mail in der Datenladung ist wahrscheinlich redundant
Obwohl dies nicht gegen REST verstößt und möglicherweise einen besonderen Zweck hat, ist es häufig nicht erforderlich, eine ID oder E-Mail-Adresse für ein Zurücksetzen des Kennworts anzugeben. Denken Sie darüber nach, warum sollten Sie die E-Mail-Adresse als Teil der Daten für eine Anfrage angeben, die auf die eine oder andere Weise authentifiziert werden soll? Wenn der Benutzer lediglich sein Passwort ändert, muss er sich dazu authentifizieren (über Benutzername: Passwort, E-Mail: Passwort oder Zugriffstoken, das über Header bereitgestellt wird). Daher haben wir ab diesem Schritt Zugriff auf ihr Konto. Wenn sie ihr Passwort vergessen hätten, hätten sie ein temporäres Reset-Token (per E-Mail) erhalten, das sie speziell als Anmeldeinformationen für die Durchführung der Änderung verwenden können. In diesem Fall sollte die Authentifizierung über ein Token ausreichen, um das Konto zu identifizieren.
Unter Berücksichtigung all dieser Punkte ist hier meines Erachtens das richtige Schema für eine RESTful-Passwortänderung:
quelle
POST
vs.PUT
RFC 7231 gibt an, dass eine teilweise Aktualisierung durch überlappende Daten von zwei Ressourcen erreicht werden kann , aber es ist fraglich , ob so etwas wie/v1/account/password
eigentlich wirklich für eine gute Ressource nicht bilden. EbensoPOST
wie der Schweizer Armee-Kniff des Webs, der verwendet werden kann, wenn keine der anderen Methoden durchführbar ist,PATCH
könnte dies auch eine Option zum Festlegen des neuen Passworts sein.Ich hätte nichts, das das Passwort ändert und ihnen ein neues sendet, wenn Sie sich für die Methode / users / {id} / password entscheiden und an Ihrer Idee festhalten, dass die Anfrage eine eigene Ressource ist. dh / user-password-request / ist die Ressource und verwendet PUT. Benutzerinformationen sollten sich im Hauptteil befinden. Ich würde das Passwort jedoch nicht ändern. Ich sende eine E-Mail an den Benutzer, die einen Link zu einer Seite enthält, die eine request_guid enthält, die zusammen mit einer Anfrage an POST / user / {id} / password /? Request_guid = übergeben werden kann xxxxx
Das würde das Passwort ändern und es erlaubt niemandem, einen Benutzer durch Anfordern einer Passwortänderung abzuspritzen.
Außerdem kann der anfängliche PUT fehlschlagen, wenn eine ausstehende Anforderung vorliegt.
quelle
Wir aktualisieren das protokollierte Benutzerkennwort PUT / v1 / users / password - identifizieren Sie die Benutzer-ID mit AccessToken.
Es ist nicht sicher, die Benutzer-ID auszutauschen. Die Restful-API muss den Benutzer anhand des im HTTP-Header empfangenen AccessToken identifizieren.
Beispiel im Spring-Boot
quelle