Menu
CoddyTech

Parolayı Doğrulama

Coddy'nin Node.js Journey'sinin Kimlik Doğrulama ve Güvenlik bölümünün bir parçası. Ders 6 / 24.

Giriş işlemi, kaydedilmiş tuzu ve özgün anahtar uzunluğunu kullanarak girilen paroladan bir anahtar türetir. Yeni bir tuz, doğru parola için bile farklı bir anahtar üretir. Özgün parola depolamadan hiçbir zaman çözülmez.

// Bir davet kodu salt.keyHex biçiminde saklandı
const [salt, keyHex] = savedInvite.split('.');
const expected = Buffer.from(keyHex, 'hex');
const attempted = await scryptAsync(inviteCode, salt, 32);

Uzunluklarının eşleştiğini doğruladıktan sonra, elde edilen bayt dizilerini timingSafeEqual kullanarak karşılaştır. Bu, zamanlama yoluyla bilgi açığa çıkarabilecek, içeriğe bağlı erken çıkışı önler. Buffer için === kimliği denetler; normal bir dize karşılaştırması ise sabit zamanlı çalışma garantisi sağlamaz. Parola işlevin, parola kaydının iki nokta üst üste ayırıcısını ve 64 baytlık anahtarını kullanır. Eklediğin POST /login rotası, sonucu 200 veya 401 döndürmek için kullanır.

challenge icon

Görev

Kolay

Bu adım, Never Store Passwords dersindeki proje dosyalarınız yerine, kurs için hazırlanmış özel notlar API projesini açar (passwords.js dahil). Önceki çalışmalarınız kendi dersinde kalır. passwords.js dosyasını düzenlemeden önce sağlanan dosyaları okuyun. Bu kopyada parola karma yardımcıları ve sağlanan hata ayıklama rotaları bulunur.

Kaydolma artık tuzlanmış özetleri kaydediyor. Kaydolma sırasında kaydedilen değerle parolayı denetleyen bir giriş işlevi ekleyin.

  1. passwords.js dosyasında async bir verifyPassword(password, stored) işlevi ekleyip dışa aktarın. stored, kaydolma sırasında kaydedilen bir değerdir; örneğin f2bb...f065:c3f7...dbd2. password bu değeri oluşturan parolaysa true, değilse false döndürün:
    • İki noktadan önceki tuzu alın.
    • password değerini bu tuzla, hashPassword işlevindekiyle aynı şekilde 64 baytlık bir anahtara dönüştürün.
    • İki noktadan sonraki kaydedilmiş anahtarı onaltılık biçimden çözün. İki anahtarın bayt uzunlukları farklıysa, Comparing Key Bytes bölümündeki gibi timingSafeEqual çağrısı yapmadan false döndürün. Aksi takdirde karşılaştırma sonucunu döndürün.
  2. server.js dosyasında, verifyPassword işlevini hashPassword işlevinin yanına içe aktarın. POST /login rotasını ekleyin. Bu rota, örneğin {"username": "ada", "password": "correct horse"} gibi kaydolma işlemiyle aynı gövdeyi alır.
    • Bu kullanıcı adına sahip kullanıcıyı bulun. verifyPassword yavaştır ve bir promise döndürür; bu nedenle tamamlanmasını bekleyin.
    • Kullanıcı varsa ve parola doğruysa 200 durum koduyla {"username": "ada"} yanıtını verin.
    • Aksi takdirde 401 durum koduyla {"error": "Wrong username or password"} yanıtını verin. 401 Unauthorized, isteğin kim olduğunu kanıtlayamadığı anlamına gelir.
    • Yanlış parola ve kimsenin kaydolmadığı bir kullanıcı adı için aynı 401 yanıtını gönderin. Böylece yanıt gövdesi, hangi kullanıcı adlarının mevcut olduğunu kimseye asla bildirmez.

Deneyin: Run düğmesine basın. POST /signup isteğini {"username": "ada", "password": "correct horse"} ile gönderin: durum kodu 201. Aynı gövdeyle POST /login isteğini gönderin: durum kodu 200 ve {"username": "ada"}. POST /login isteğini {"username": "ada", "password": "wrong horse"} ile gönderin: durum kodu 401 ve {"error": "Wrong username or password"}. POST /login isteğini {"username": "nobody", "password": "correct horse"} ile gönderin: aynı 401 yanıtı.

Kendin dene

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

const scryptAsync = promisify(scrypt);

// Bir parolayı signup'ın sakladığı metne dönüştürür.
export async function hashPassword(password) {
    const salt = randomBytes(16).toString('hex');
    const key = await scryptAsync(password, salt, 64);
    return `${salt}:${key.toString('hex')}`;
}

Kimlik Doğrulama ve Güvenlik bölümündeki tüm dersler

Kendi başına pratik yap: Express playground