İçeriğe atla
Yazılım Geliştirme

Next.js Server Actions ile Güvenli Form İşleme

Server Actions form işlemeyi sadeleştiriyor, ancak güvenliği otomatik olarak sağlamıyor. Doğrulama, CSRF, oran sınırlama ve yetkilendirme katmanlarını nasıl kurmalı?

HHeracleWeb Dijital Ajans2 dakika okuma

Next.js Server Actions, form gönderimini ayrı bir API rotası yazmadan doğrudan sunucuda işlemeyi mümkün kılıyor. Bu ciddi bir sadeleşme; ancak "sunucuda çalışıyor" olmak "güvenli" anlamına gelmiyor.

1. Girdiyi her zaman sunucuda doğrulayın

İstemci tarafındaki doğrulama bir kullanıcı deneyimi özelliğidir, güvenlik önlemi değil. Saldırgan tarayıcıyı hiç kullanmadan doğrudan istek gönderebilir.

Her Server Action, FormData içeriğini bir şema ile doğrulamalı:

const parsed = contactSchema.safeParse({
  name: formData.get('name'),
  email: formData.get('email'),
  message: formData.get('message'),
});

if (!parsed.success) {
  return { ok: false, errors: parsed.error.flatten().fieldErrors };
}

Dikkat edilmesi gereken nokta: formData.get() string | File | null döner. Şemanız bunu karşılamıyorsa çalışma zamanında beklenmedik davranış oluşur.

2. Yetkilendirmeyi action içinde yapın

Bir düğmeyi arayüzde gizlemek yetkilendirme değildir. Server Action'lar HTTP uç noktalarıdır ve doğrudan çağrılabilirler.

Bu yüzden her action, ilk satırlarında oturumu ve yetkiyi kontrol etmelidir:

const session = await getSession();
if (!session) throw new AuthorizationError('Oturum gerekli', 401);
if (!can(session.role, 'blog:publish')) throw new AuthorizationError();

Bu kontrolü bir yardımcı fonksiyona taşıyıp her action'ın başında çağırmak, unutma riskini azaltır.

3. CSRF korumasını hafife almayın

Next.js, Server Actions için Origin başlığını Host ile karşılaştırır. Bu iyi bir temel koruma; ancak API rotalarınız varsa veya proxy arkasında Host başlığı değişiyorsa, kendi kontrolünüzü de eklemek gerekir.

Oturuma bağlı bir token en sağlam yaklaşımdır: HMAC(secret, "csrf:" + sessionId) değerini forma gizli alan olarak koyup sunucuda sabit zamanlı karşılaştırma ile doğrulayın. Saldırgan bu değeri ne üretebilir ne de çapraz kaynaktan okuyabilir.

4. Oran sınırlaması ekleyin

Bir iletişim formu, oran sınırı olmadan spam botları için açık davetiyedir. Giriş formu ise kaba kuvvet saldırısına açıktır.

Kritik nokta: sayaçları yalnızca bellekte tutmayın. Uygulamayı yeniden başlatabilen bir saldırgan kilitlenmeyi sıfırlayabilir. Giriş denemeleri gibi kritik sayaçları diske de yazın.

Ayrıca hem IP hem hesap bazında sınırlayın. Yalnızca IP bazlı sınır, dağıtık saldırıyı durdurmaz; yalnızca hesap bazlı sınır ise kullanıcı numaralandırmaya (enumeration) açık kapı bırakır.

5. Hata mesajlarınızı sızdırmayın

Giriş başarısız olduğunda "böyle bir kullanıcı yok" demek, saldırgana geçerli e-posta adreslerini tarama imkânı verir. Doğru davranış, kullanıcı bulunamadığında da sahte bir hash doğrulaması çalıştırıp aynı genel mesajı dönmektir:

const user = await findByEmail(email);
if (!user) {
  await verifyPassword(DUMMY_HASH, password); // zamanlama farkını kapat
  return { ok: false, message: 'E-posta veya şifre hatalı.' };
}

6. Yeniden doğrulamayı unutmayın

Bir içerik güncellendiğinde revalidatePath çağrılmazsa, kullanıcı eski önbelleklenmiş sayfayı görmeye devam eder. Yayınla düğmesine basan editörün "değişiklik görünmüyor" demesi genellikle bu sebeptendir.

Özet

Server Actions, boilerplate'i azaltıyor ama sorumluluğu azaltmıyor. Doğrulama, yetkilendirme, CSRF, oran sınırlama ve önbellek geçersizleştirme — bu beş katman her action için ayrı ayrı düşünülmeli.

Projenizi birlikte konuşalım

Fikrinizi, mevcut sisteminizi ya da büyüme hedefinizi anlatın; teknik yaklaşımı, süreci ve zaman planını net biçimde paylaşalım.