Menu
CoddyTech

Sprawdzanie hasła

Część sekcji Uwierzytelnianie i bezpieczeństwo ścieżki Node.js w Coddy. Lekcja 6 z 24.

Podczas logowania na podstawie wprowadzonego hasła wyprowadzany jest klucz przy użyciu zapisanego soli i oryginalnej długości klucza. Nowa sól dałaby inny klucz, nawet dla prawidłowego hasła. Oryginalne hasło nigdy nie jest odczytywane z pamięci.

// Kod zaproszenia zapisano w postaci salt.keyHex
const [salt, keyHex] = savedInvite.split('.');
const expected = Buffer.from(keyHex, 'hex');
const attempted = await scryptAsync(inviteCode, salt, 32);

Porównaj otrzymane sekwencje bajtów za pomocą timingSafeEqual, po potwierdzeniu, że mają tę samą długość. Zapobiega to zależnemu od zawartości wcześniejszemu zakończeniu działania, które mogłoby ujawnić informacje przez pomiar czasu. Operator === dla obiektów Buffer sprawdza tożsamość, a zwykłe porównanie ciągów znaków nie gwarantuje stałego czasu wykonania. Twoja funkcja hasła używa dwukropka jako separatora w rekordzie hasła oraz klucza o długości 64 bajtów. Dodana przez Ciebie trasa POST /login używa wyniku, aby zwrócić kod 200 lub 401.

challenge icon

Wyzwanie

Łatwy

Ten krok otwiera przygotowany projekt API prywatnych notatek kursu, a nie pliki Twojego projektu z lekcji Nigdy nie przechowuj haseł (w tym passwords.js). Twoja wcześniejsza praca pozostaje w swojej własnej lekcji. Przeczytaj dostarczone pliki przed edycją passwords.js. Ta kopia zawiera funkcje pomocnicze do haszowania haseł oraz dostarczone trasy debugowania.

Rejestracja zapisuje teraz hasze z solą. Dodaj logowanie, które sprawdza hasło względem tego, co zapisała rejestracja.

  1. W pliku passwords.js dodaj i eksportuj funkcję async verifyPassword(password, stored). stored to wartość zapisana podczas rejestracji, na przykład f2bb...f065:c3f7...dbd2. Zwróć true, gdy password jest hasłem, które ją utworzyło, a w przeciwnym razie false:
    • Pobierz sól znajdującą się przed dwukropkiem.
    • Przekształć password przy użyciu tej soli w klucz o długości 64 bajtów, tak samo jak robi to hashPassword.
    • Odkoduj zap zapisany klucz znajdujący się po dwukropku z formatu szesnastkowego. Jeśli długości kluczy w bajtach są różne, zwróć false bez wywoływania timingSafeEqual, tak jak w lekcji „Porównywanie bajtów klucza”. W przeciwnym razie zwróć wynik porównania.
  2. W pliku server.js zaimportuj verifyPassword obok hashPassword. Dodaj POST /login. Otrzymuje ono takie samo ciało żądania jak rejestracja, na przykład {"username": "ada", "password": "correct horse"}.
    • Znajdź użytkownika o podanej nazwie użytkownika. verifyPassword działa wolno i zwraca obietnicę, więc poczekaj na jej rozwiązanie.
    • Jeśli użytkownik istnieje, a hasło jest poprawne, odpowiedz statusem 200 i treścią {"username": "ada"}.
    • W przeciwnym razie odpowiedz statusem 401 i treścią {"error": "Wrong username or password"}. 401 Unauthorized oznacza, że żądanie nie potwierdziło, kto je wysyła.
    • Wysyłaj dokładnie taką samą odpowiedź 401 w przypadku błędnego hasła i nazwy użytkownika, dla której nikt się nie zarejestrował. Dzięki temu treść odpowiedzi nigdy nie ujawni nikomu, które nazwy użytkowników istnieją.

Wypróbuj: Naciśnij „Graj”. Wyślij POST /signup z treścią {"username": "ada", "password": "correct horse"}: status 201. Wyślij POST /login z tą samą treścią: status 200 i {"username": "ada"}. Wyślij POST /login z treścią {"username": "ada", "password": "wrong horse"}: status 401 i {"error": "Wrong username or password"}. Wyślij POST /login z treścią {"username": "nobody", "password": "correct horse"}: ten sam status 401.

Spróbuj swoich sił

import { randomBytes, scrypt } from 'node:crypto';
import { promisify } from 'node:util';

const scryptAsync = promisify(scrypt);

// Przekształca hasło w tekst przechowywany przez signup.
export async function hashPassword(password) {
    const salt = randomBytes(16).toString('hex');
    const key = await scryptAsync(password, salt, 64);
    return `${salt}:${key.toString('hex')}`;
}

Wszystkie lekcje w sekcji Uwierzytelnianie i bezpieczeństwo

Poćwicz samodzielnie: Edytor online Express