Jaki jest właściwy sposób zorganizowania zasobu RESTful do resetowania hasła?
Ten zasób ma służyć do resetowania hasła dla kogoś, kto zgubił lub zapomniał hasła. Unieważnia ich stare hasło i wysyła je e-mailem.
Dwie opcje, które mam, to:
POST /reset_password/{user_name}
lub...
POST /reset_password
-Username passed through request body
Jestem prawie pewien, że żądanie powinno być POST. Jestem mniej przekonany, że wybrałem odpowiednią nazwę. I nie jestem pewien, czy nazwa_użytkownika powinna być przekazywana za pośrednictwem adresu URL, czy treści żądania.
źródło
Nieuwierzytelnieni użytkownicy
Wykonujemy
PUT
żądanie naapi/v1/account/password
punkcie końcowym i wymagamy parametru z odpowiednim adresem e-mail konta, aby zidentyfikować konto, dla którego użytkownik chce zresetować (zaktualizować) hasło:Uwaga: Jak wspomniał @DougDomeny w swoim komentarzu, przekazywanie wiadomości e-mail jako ciągu zapytania w adresie URL stanowi zagrożenie bezpieczeństwa. Parametry GET nie są ujawniane podczas używania
https
(ihttps
do takich żądań należy zawsze używać odpowiedniego połączenia), ale istnieją inne zagrożenia bezpieczeństwa. Możesz przeczytać więcej na ten temat w tym wpisie na blogu tutaj .Przekazanie e-maila w treści żądania byłoby bezpieczniejszą alternatywą dla przekazania go jako parametru GET:
Treść żądania:
Odpowiedź ma
202
zaakceptowaną odpowiedź, co oznacza:Użytkownik otrzyma wiadomość e-mail na adres,
[email protected]
a przetwarzanie żądania aktualizacji zależy od działań podjętych za pomocą łącza z wiadomości e-mail.Otwarcie linku z tego e-maila spowoduje przekierowanie do formularza resetowania hasła w aplikacji frontonu, który używa tokena resetowania hasła z linku jako danych wejściowych dla ukrytego pola wejściowego (token jest częścią łącza jako ciąg zapytania). Kolejne pole wejściowe umożliwia użytkownikowi ustawienie nowego hasła. Drugie wejście w celu potwierdzenia nowego hasła zostanie użyte do weryfikacji na interfejsie użytkownika (aby zapobiec literówkom).
Uwaga: w e-mailu możemy również wspomnieć, że jeśli użytkownik nie zainicjował żadnego resetowania hasła, może zignorować wiadomość e-mail i normalnie korzystać z aplikacji z obecnym hasłem
Po przesłaniu formularza z nowym hasłem i tokenem jako danymi wejściowymi nastąpi proces resetowania hasła. Dane formularza zostaną ponownie wysłane z
PUT
żądaniem, ale tym razem z tokenem i zastąpimy hasło zasobu nową wartością:Treść żądania:
Odpowiedź będzie
204
brak zawartości odpowiedźUwierzytelnieni użytkownicy
W przypadku uwierzytelnionych użytkowników, którzy chcą zmienić swoje hasło,
PUT
żądanie może zostać zrealizowane natychmiast, bez wiadomości e-mail (konto, dla którego aktualizujemy hasło, jest znane serwerowi). W takim przypadku formularz będzie zawierał dwa pola:Treść żądania:
źródło
Uzyskajmy Uber-RESTful na sekundę. Dlaczego nie użyć akcji USUŃ dla hasła, aby wywołać reset? To ma sens, prawda? W końcu skutecznie odrzucasz istniejące hasło na rzecz innego.
Oznacza to, że zrobiłbyś:
Teraz dwa duże zastrzeżenia:
HTTP DELETE ma być idempotentne (wymyślne słowo na określenie „nic wielkiego, jeśli robisz to wiele razy”). Jeśli wykonujesz standardowe czynności, takie jak wysyłanie wiadomości e-mail „Resetowanie hasła”, napotkasz problemy. Możesz obejść ten problem, oznaczając użytkownika / hasło logiczną flagą „Czy resetowano”. Przy każdym usunięciu zaznaczasz tę flagę; jeśli nie jest ustawiona , a następnie można zresetować hasło i wysyłać wiadomości e-mail. (Zauważ, że posiadanie tej flagi może mieć również inne zastosowania).
Nie możesz użyć HTTP DELETE przez formularz , więc będziesz musiał wykonać wywołanie AJAX i / lub tunelować DELETE przez POST.
źródło
DELETE
odpowiedniego dopasowania. Myślę, że zastąpiłbyś hasło losowo wygenerowanym hasłem, więcDELETE
może być mylące. WolęCreate (POST) new reset_password action
, gdzie rzeczownik (zasób), na którym będziesz działać, to akcja „reset_password”. Pasuje to również do wysyłania e-maili, ponieważ akcja zawiera wszystkie te szczegóły niższego poziomu.POST
nie jest idempotentny.Często nie chcesz usuwać ani niszczyć istniejącego hasła użytkownika przy pierwszym żądaniu, ponieważ mogło to zostać uruchomione (nieumyślnie lub celowo) przez użytkownika, który nie ma dostępu do wiadomości e-mail. Zamiast tego zaktualizuj token resetowania hasła w rekordzie użytkownika i wyślij go w łączu zawartym w wiadomości e-mail. Kliknięcie linku potwierdzałoby, że użytkownik otrzymał token i chciał zaktualizować swoje hasło. W idealnym przypadku byłoby to również wrażliwe na czas.
Akcją RESTful w tym przypadku byłoby POST: wyzwalanie akcji tworzenia na kontrolerze PasswordResets. Sama akcja zaktualizowałaby token i wysłała wiadomość e-mail.
źródło
Właściwie szukam odpowiedzi, nie mam zamiaru jej udzielić - ale „reset_password” brzmi dla mnie źle w kontekście REST, ponieważ jest to czasownik, a nie rzeczownik. Nawet jeśli powiesz, że wykonujesz rzeczownik „resetuj akcję” - używając tego uzasadnienia, wszystkie czasowniki są rzeczownikami.
Ponadto komuś szukającemu tej samej odpowiedzi mogło nie przyjść do głowy, że możesz uzyskać nazwę użytkownika w kontekście bezpieczeństwa i nie musisz w ogóle przesyłać jej przez adres URL lub treść, co mnie denerwuje.
źródło
reset-password
brzmi jak czasownik, ale można go łatwo odwrócić (password-reset
), aby uczynić go rzeczownikiem. A jeśli modelowałeś swoją aplikację przy użyciu funkcji Event Sourcing lub nawet jeśli masz po prostu jakiś rodzaj audytu, sensowne jest, że faktycznie masz prawdziwą jednostkę o tej nazwie i możesz nawet zezwolić na GET dla użytkowników lub administratorów historia (oczywiście maskowanie tekstu hasła). W ogóle mnie to nie denerwuje. A jeśli chodzi o automatyczne pobieranie nazwy użytkownika po stronie serwera - możesz, ale jak radzisz sobie z takimi rzeczami, jak administracja / podszywanie się?reset-password
dobrze opisuję jego efekty.Myślę, że lepszym pomysłem byłoby:
W zakresie podania danych:
Aby zresetować aktualne hasło
Tworzenie nowego hasła (po zresetowaniu)
Aby zaktualizować hasło (dla zalogowanego użytkownika)
źródło
Należy wziąć pod uwagę kilka kwestii:
Resetowanie haseł nie jest idempotentne
Zmiana hasła wpływa na dane używane jako poświadczenia do jej wykonania, co w rezultacie może unieważnić przyszłe próby, jeśli żądanie zostanie po prostu powtórzone dosłownie, podczas gdy zapisane poświadczenia ulegną zmianie. Na przykład, jeśli tymczasowy token resetowania jest używany w celu umożliwienia zmiany, jak to jest zwykle w sytuacji zapomnienia hasła, ten token powinien wygasnąć po pomyślnej zmianie hasła, co ponownie unieważnia dalsze próby replikacji żądania. Dlatego podejście RESTful do zmiany hasła wydaje się być pracą lepiej dostosowaną
POST
niżPUT
.Identyfikator lub e-mail w ładowaniu danych jest prawdopodobnie zbędny
Chociaż nie jest to sprzeczne z REST i może mieć jakiś specjalny cel, często nie jest konieczne określanie identyfikatora lub adresu e-mail w celu zresetowania hasła. Pomyśl o tym, dlaczego miałbyś podawać adres e-mail jako część danych do żądania, które ma przejść przez uwierzytelnienie w taki czy inny sposób? Jeśli użytkownik po prostu zmienia swoje hasło, musi się uwierzytelnić, aby to zrobić (poprzez nazwę użytkownika: hasło, e-mail: hasło lub token dostępu podany w nagłówkach). Dlatego na tym etapie mamy dostęp do ich konta. Gdyby zapomnieli hasła, otrzymaliby tymczasowy token resetowania (za pośrednictwem poczty e-mail), którego mogą użyć w szczególności jako poświadczeń do wykonania zmiany. I w tym przypadku uwierzytelnienie za pomocą tokena powinno wystarczyć do zidentyfikowania konta.
Biorąc pod uwagę wszystkie powyższe kwestie, oto, co uważam za właściwy schemat zmiany hasła RESTful:
źródło
POST
doPUT
RFC 7231 określa, że częściową aktualizację można osiągnąć poprzez nakładanie się danych z dwóch zasobów, ale wątpliwe jest, czy coś takiego/v1/account/password
naprawdę nadrabia dobry zasób. Podobnie jak w przypadkuPOST
sieci swiss-army-kniff, której można użyć, jeśli żadna z innych metod nie jest wykonalna, rozważeniePATCH
również może być wyborem dla ustawienia nowego hasła.Nie chciałbym mieć czegoś, co zmienia hasło i wyśle im nowe, jeśli zdecydujesz się użyć metody / users / {id} / password i trzymasz się swojego pomysłu, że żądanie jest własnym zasobem. tj. / user-password-request / jest zasobem i używa PUT, informacje o użytkowniku powinny znajdować się w treści. Nie chciałbym jednak zmieniać hasła, wyślę e-mail do użytkownika, który zawiera link do strony zawierającej request_guid, który można przekazać wraz z żądaniem do POST / user / {id} / password /? Request_guid = xxxxx
To spowodowałoby zmianę hasła i nie pozwala komuś nakłonić użytkownika do żądania zmiany hasła.
Ponadto początkowe PUT może się nie powieść, jeśli istnieje oczekujące żądanie.
źródło
Aktualizujemy hasło zalogowanego użytkownika PUT / v1 / users / password - zidentyfikuj identyfikator użytkownika za pomocą AccessToken.
Wymiana identyfikatora użytkownika nie jest bezpieczna. Restful API musi identyfikować użytkownika za pomocą AccessToken otrzymanego w nagłówku HTTP.
Przykład w butach wiosennych
źródło