Lompat ke konten
Kembali ke modul

API, Autentikasi, dan Keamanan · 2/7

Validasi di batas kepercayaan

Apa pun yang bisa dikirim pengguna, bisa dipalsukan pengguna. Di mana memeriksanya, dan apa yang dilakukan saat gagal.

Baca 30 menit

Setelah pelajaran ini kamu bisa

  • Menyebutkan di mana tepatnya batas kepercayaan itu
  • Memvalidasi bentuk, type, dan aturan bisnis secara terpisah
  • Menjelaskan dan mencegah mass assignment
  • Memakai library skema alih-alih pemeriksaan manual

Batas kepercayaan adalah titik mana pun di mana data datang dari tempat yang tidak kamu kendalikan. Semua yang menyeberanginya bersifat bermusuhan sampai terbukti sebaliknya — bukan karena penggunamu penyerang, tapi karena kamu tidak bisa membedakannya.

SumberDipercaya?
Kiriman formTidak
Parameter URL atau query stringTidak
Body request JSONTidak
Isi sebuah cookieTidak — penggunanya bisa mengeditnya
Argument Server ActionTidak — bisa dijangkau lewat POST langsung
Response API pihak ketigaTidak — mereka berubah tanpa memberitahumu
Body webhookTidak — sampai signature-nya terverifikasi
Database milikmu sendiriSebagian besar — kualitasnya sebatas apa yang kamu izinkan masuk

Validasi punya tiga tugas berbeda, dan mencampuradukkannya adalah sebab kode validasi jadi berantakan.

  1. Bentuk — apakah ini object dengan field yang saya harapkan, dan tidak lebih?
  2. Type dan rentang — apakah nights bilangan bulat antara 1 dan 30?
  3. Aturan bisnis — apakah venue-nya benar-benar kosong di tanggal itu? Ini butuh database, jadi ia datang terakhir.

Mass assignment

Ini celah yang muncul dari memercayai *bentuk* sebuah payload. Kamu mengambil seluruh body-nya lalu menyerahkannya ke database-mu, dan penyerangnya menyertakan field yang tidak pernah kamu maksudkan bisa mereka atur.

Coba sendiri

Satu field tambahan di body request. Lihat apa yang dicapainya terhadap masing-masing versi.

Hasil

Tekan Jalankan untuk melihat hasilnya.

Ini jalan di browser kamu, di dalam sandbox. Apa pun yang kamu tulis di sini tidak bisa merusak situs.

Library skema

Pemeriksaan manual memang bekerja — validateCredentials di proyek ini tiga puluh baris untuk dua field — tapi ia sulit diperbesar dan bisa menyimpang dari type-mu. Library skema memvalidasi sekaligus menghasilkan type TypeScript dari satu definisi.

ts
import { z } from "zod";

const BookingSchema = z.object({
  venueId: z.number().int().positive(),
  guest: z.string().trim().min(2).max(60),
  nights: z.number().int().min(1).max(30),
  email: z.string().email(),
  notes: z.string().max(500).optional(),
});

// The type is DERIVED from the schema - they cannot drift apart.
type Booking = z.infer<typeof BookingSchema>;

export async function createBooking(formData: FormData) {
  const result = BookingSchema.safeParse({
    venueId: Number(formData.get("venueId")),
    guest: formData.get("guest"),
    nights: Number(formData.get("nights")),
    email: formData.get("email"),
  });

  if (!result.success) {
    // Per-field messages, in the shape the form already expects.
    return { error: "validation_failed", fields: result.error.flatten().fieldErrors };
  }

  // result.data is fully typed AND checked. Unknown keys are stripped.
  await insertBooking(result.data);
}
safeParse mengembalikan sebuah hasil alih-alih melempar, jadi jalur error-nya eksplisit. Perhatikan key yang tidak dikenal dibuang secara default — perlindungan mass assignment, gratis.

Tugas praktik

Tulis ulang validateCredentials di proyek ini memakai zod, dengan mempertahankan key error yang sama supaya dictionary-nya tetap bekerja. Jalankan bun run test validate untuk memastikan setiap test yang ada tetap lolos — test-nya adalah spesifikasinya, dan seharusnya tidak perlu diubah.

Hasil yang diharapkan

Semua test validasi yang ada lolos terhadap implementasi baru.