Załóżmy, że mam interfejs API REST, który służy również do ustawiania / resetowania haseł. Załóżmy również, że działa to w przypadku połączeń HTTPS. Czy jest jakiś dobry powód, aby nie umieszczać tego hasła w ścieżce wywołania, powiedzmy też, że zakoduję je w BASE64?
Przykładem może być zresetowanie hasła takiego:
http://www.example.com/user/joe/resetpassword/OLDPASSWD/NEWPASSWD
Rozumiem, że BASE64 nie jest szyfrowaniem, ale w tym przypadku chcę tylko zabezpieczyć hasło do surfowania po ramieniu.
resetpassword/OLDPASSWD/NEWPASSWD
nie jest zasobem. To wywołanie procesu. Nie musisz umieszczać wszystkiego w adresie URL.Odpowiedzi:
Dobry serwer rejestruje wszystkie wysłane do niego żądania, w tym adresy URL (często bez części zmiennej po „?”), Źródłowy adres IP, czas wykonania ... Czy naprawdę chcesz, aby ten dziennik (potencjalnie czytany przez szeroką grupę administratorów) zawierał krytycznie bezpieczne informacje jako hasła? Base64 nie stanowi dla nich przeszkody.
źródło
To, co proponujesz, nie jest ani bezpieczne, ani RESTful.
@Netch wspomniał już o problemie z logami, ale jest też inny problem polegający na tym, że wyświetlasz hasła wysyłane przez HTTP, dzięki czemu przechwytywanie haseł za pomocą dowolnego podsłuchu lub ataku typu man-in-the-trywialnego jest banalne.
Kiedy wykonujesz żądanie GET przy użyciu REST, różne elementy w adresie URL reprezentują elementy o drobniejszych ziarnach. Twój adres URL brzmi, jakbyś zwrócił NEWPASSWD część OLDPASSWD, która jest częścią hasła resetowania. To nie ma żadnego sensu semantycznego. GET nie powinny być używane do zapisywania danych.
Powinieneś robić coś takiego:
POST, ponieważ piszesz dane, a https, ponieważ nie chcesz, aby były wąchane.
(To naprawdę niskie bezpieczeństwo. Absolutne minimum, które powinieneś zrobić.)
źródło
/user/joe/password
jest trochę lepiej, ale nie optymalne.PUT
, ponieważPUT
jest idempotentny. Ale jeśli hasło zostanie zmienione zsecret
nasupersecret
pomyślnie, to samo żądanie nie powiedzie się za drugim razem, więcPOST
tutaj jest poprawne. Oczywiście, jak powiedział @whirlwin, ten zasób nie jest dobrze nazwany.Proponowany program ma problemy w kilku obszarach.
Bezpieczeństwo
Ścieżki URL są często rejestrowane; stawianie niepasujących haseł na ścieżce to zła praktyka.
HTTP
Informacje o uwierzytelnieniu / autoryzacji powinny pojawić się w nagłówku autoryzacji. Lub potencjalnie, w przypadku rzeczy opartych na przeglądarce, nagłówek Cookie.
RESZTA
Czasowniki, takie jak
resetpassword
w adresie URL, są zazwyczaj wyraźnym znakiem niereprezentatywnego paradygmatu transferu stanu. Adres URL powinien reprezentować zasób. Co to znaczy GETresetpassword
? Lub USUŃ?API
Ten schemat wymaga zawsze znajomości poprzedniego hasła. Prawdopodobnie będziesz chciał pozwolić na więcej przypadków; np. hasło zostało utracone.
Możesz użyć uwierzytelniania podstawowego lub szyfrowanego , które są dobrze zrozumiałymi schematami.
Nie umieszcza ultra wrażliwych informacji na ścieżce i postępuje zgodnie z konwencjami HTTP i REST.
Jeśli musisz zezwolić na inny tryb autoryzacji (np. Token wysłany przez zweryfikowany kanał w celu zresetowania hasła), możesz po prostu użyć innego nagłówka autoryzacji bez konieczności zmiany czegokolwiek innego.
źródło
Poza bezpieczeństwem problem polega na tym, że nie jest to podejście RESTful.
OLDPASSWD
iNEWPASSWD
nie oznacza niczego w hierarchii zasobów, a co gorsza, operacja nie jest idempotentna.Możesz więc używać tylko
POST
jako czasownika i nie powinieneś dołączać dwóch haseł do ścieżki zasobów.źródło
PUT
jest dyskwalifikowana jako czasownik. Można z niego korzystać,PUT
ale w obecnej formie tak nie jest.Problem polega na unikaniu haseł w postaci zwykłego tekstu w żądaniach. Istnieją dwie opcje spełnienia restrykcyjnych wymagań usługi internetowej.
1. Hashowanie po stronie klienta
2. Szyfrowanie
Uwaga: HTTPS jest wymagany dla obu opcji!
źródło
Jakie są funkcje operacji resetowania hasła?
Punkt 1 tutaj oznacza, że nie możesz użyć GET, musisz albo POST wysłać coś reprezentującego operację zmiany hasła do identyfikatora URI reprezentującego zasób, który obsługuje zmiany hasła, lub PUT coś reprezentującego nowe hasło do identyfikatora URI reprezentującego hasło lub reprezentującego coś (np. użytkownika), którego hasło jest funkcją.
Zazwyczaj POST, zwłaszcza dlatego, że może być niewygodne WYKŁADANIE czegoś, czego nie możemy później uzyskać i oczywiście nie możemy uzyskać hasła.
Punkt 2 będzie zatem danymi reprezentującymi nowe hasło, w tym, co jest POST.
Punkt 3 oznacza, że będziemy musieli autoryzować żądanie, co oznacza, że jeśli użytkownik jest bieżącym użytkownikiem, będziemy potrzebować aktualnego hasła, aby nam je udowodnić (choć niekoniecznie otrzymamy aktualne hasło, jeśli np. Wyzwanie oparte na haszowaniu służyło do udowodnienia znajomości go bez wysyłania go).
URI powinien zatem być podobny do
<http://example.net/changeCurrentUserPassword>
lub<http://example.net/users/joe/changePassword>
.Możemy zdecydować, że chcemy otrzymać aktualne hasło w danych POST, a także w ogólnym mechanizmie autoryzacji.
źródło