CaYaDev Logo
  • Ana Sayfa
  • Projeler
  • Paylaşımlar
  • Destek
  • Profil
    Ayarlar Çıkış
    Giriş Kayıt Ol
Paylaşımlara Dön

Express.js Uygulamanızı Güvene Almak: Oturumlar, CSRF ve Hız Sınırlama

CaYatur C
Paylaşan CaYatur Yönetici hesabı · @CaYatur
14.06.2026 21:45
Güvenlik
0
Express.js Uygulamanızı Güvene Almak

Express.js Uygulamanızı Güvene Almak: Oturumlar, CSRF ve Hız Sınırlama

Express ile bir uygulamayı ayağa kaldırmak yarım saat sürer; onu internete açmaya hazır hâle getirmek ise başka bir iştir. Bu sitenin altyapısını yazarken güvenlik katmanlarını tek tek elden geçirdim, hatta CSRF korumasını doğrulamak için kendime küçük bir test takımı bile yazdım. Bu yazı, o süreçte öğrendiklerimin damıtılmış hâli: bir Express uygulamasında ilk günden kapatmanız gereken kapılar.

Oturum çerezlerini sıkılaştırın

Oturum tabanlı kimlik doğrulamada güvenliğin yarısı çerez ayarlarındadır:

app.use(session({
  secret: process.env.SESSION_SECRET, // koda değil, ortam değişkenine
  resave: false,
  saveUninitialized: false,
  cookie: {
    httpOnly: true,   // JavaScript çerezi okuyamaz (XSS'e karşı)
    secure: true,     // yalnızca HTTPS üzerinden gönderilir
    sameSite: 'lax',  // başka siteden gelen isteklere eklenmez
    maxAge: 1000 * 60 * 60 * 24 * 7
  }
}));

Üç bayrağın üçü de ayrı bir saldırı sınıfını kapatır: httpOnly çalınan bir XSS açığının oturumu kaçırmasını, secure ağdaki dinleyicileri, sameSite ise CSRF saldırılarının önemli bir kısmını engeller. secret değerinin kodda değil .env dosyasında durması ise pazarlık konusu bile değildir — depoya sızmış bir oturum anahtarı, tüm kullanıcı oturumlarının sahteleneblmesi demektir.

CSRF: kullanıcınızın tarayıcısı size karşı

Cross-Site Request Forgery, kötü niyetli bir sitenin, sizin sitenizde oturumu açık olan kullanıcının tarayıcısına istek attırmasıdır. Kullanıcı farkında bile olmadan "profil sil" ya da "paylaşım oluştur" isteği gönderilebilir.

Savunmanın özü: durum değiştiren her istek (POST/PUT/DELETE), yalnızca sizin sayfanızın üretebileceği bir kanıt taşımalı. Klasik çözüm, oturuma bağlı bir CSRF token'ıdır:

// Token üret ve şablona ver
res.render('form', { csrfToken: req.session.csrfToken });

// Durum değiştiren isteklerde doğrula
app.post('/api/shares', (req, res, next) => {
  const sent = req.headers['x-csrf-token'] || req.body._csrf;
  if (!sent || sent !== req.session.csrfToken) {
    return res.status(403).json({ error: 'Geçersiz CSRF token' });
  }
  next();
});

sameSite: 'lax' çerezi bu saldırıların çoğunu zaten engeller; ama eski tarayıcılar ve bazı kenar durumlar için token katmanını tutmak hâlâ doğru bir karar. Kendi uygulamamda korumayı yazdıktan sonra, kasıtlı olarak token'sız ve yanlış token'lı istekler gönderen bir test betiğiyle her kritik uç noktayı tek tek denedim. Tavsiye ederim: güvenlik kodu, başarısız olması gereken senaryolarla test edilmedikçe yazılmış sayılmaz.

Hız sınırlama: kaba kuvvetin panzehiri

Giriş formunuz hız sınırı olmadan yayındaysa, birisi şu anda şifre deniyor olabilir. express-rate-limit ile dakikalar içinde temel koruma kurulur:

const rateLimit = require('express-rate-limit');

const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,  // 15 dakika
  max: 10,                   // IP başına 10 deneme
  message: { error: 'Çok fazla deneme. Lütfen sonra tekrar deneyin.' }
});

app.post('/api/login', loginLimiter, loginHandler);

Önemli ayrıntı: genel bir sınır her uç nokta için aynı olmamalı. Giriş, kayıt ve şifre sıfırlama gibi hassas uç noktalara sıkı; genel API'ye daha gevşek sınırlar koyun. Cloudflare gibi bir vekil arkasındaysanız app.set('trust proxy', ...) ayarını yapmadan IP tabanlı sınırlama çalışmaz — tüm istekler vekilin IP'sinden geliyor görünür ve tek kötü niyetli kullanıcı, herkesin limitini tüketebilir.

Express güvenlik katmanları: istek sunucuya ulaşmadan geçtiği kontroller

Girdiye asla güvenmeyin

Sunucuya ulaşan her veri — form alanı, URL parametresi, başlık, çerez — saldırgan kontrolünde olabilir. İki temel kural:

1. Sorguları her zaman parametreyle yazın. SQL enjeksiyonunun çözümü 20 yıldır aynı:

// ASLA: "SELECT * FROM users WHERE name = '" + isim + "'"
db.get('SELECT * FROM users WHERE username = ?', [isim], cb);

2. Çıktıyı bağlamına göre kaçışlayın. Kullanıcıdan gelen metni HTML'e gömmeden önce <, >, " gibi karakterleri dönüştürün; aksi hâlde sakladığınız veri, başka bir kullanıcının tarayıcısında çalışan koda (stored XSS) dönüşür. Markdown kabul ediyorsanız, üretilen HTML'i mutlaka bir sanitizer'dan geçirin.

Dosya yüklemenin sessiz tuzakları

Dosya yükleme, en masum görünen ama en çok istismar edilen özelliktir. Multer kullanıyorsanız asgari önlemler:

const upload = multer({
  storage: diskStorage,
  limits: { fileSize: 2 * 1024 * 1024 },  // boyut sınırı şart
  fileFilter: (req, file, cb) => {
    const izinli = ['image/jpeg', 'image/png', 'image/webp'];
    cb(null, izinli.includes(file.mimetype));
  }
});

Buna ek olarak: dosya adını asla kullanıcıdan geldiği gibi kullanmayın (yol kaçışı ../../ saldırıları), kendi ürettiğiniz rastgele bir adla kaydedin ve yüklenen dosyaların bulunduğu klasörde betik çalıştırılamadığından emin olun. MIME türü istemci beyanıdır; kritik sistemlerde dosyanın gerçek içeriğini de (magic bytes) doğrulayın.

Başlıklar ve küçük ama etkili dokunuşlar

  • helmet paketi tek satırla güvenlik başlıklarını ayarlar: app.use(helmet()). İçerik Güvenliği Politikası'nı (CSP) sitenize göre yapılandırmak biraz uğraştırır ama XSS'e karşı en güçlü ikinci savunmadır.
  • X-Powered-By: Express başlığını kapatın: app.disable('x-powered-by'). Saldırgana teknoloji bilgisi vermenin kimseye faydası yok.
  • Hata mesajlarında yığın izini (stack trace) asla kullanıcıya göstermeyin; loglayın, kullanıcıya genel bir mesaj dönün.
  • Admin uç noktalarını yalnızca oturum kontrolüyle değil, yetki kontrolüyle koruyun: "giriş yapmış" ile "admin" aynı şey değildir.

Sonuç

Express güvenliği tek bir paket kurmakla bitmez; katmanların toplamıdır: sıkı çerezler oturumu, CSRF token'ı kullanıcının tarayıcısını, hız sınırı giriş formunu, parametreli sorgular veritabanını, kaçışlama diğer kullanıcıları korur. İyi haber şu ki bu katmanların hiçbiri tek başına büyük iş değildir — hepsi birer öğleden sonralık iş, ama hepsi birden uygulamanızı internetin gürültüsüne dayanıklı hâle getirir. Önce giriş uç noktanızdan başlayın; orası her zaman ilk denenen kapıdır.
gorsel-1.png

Ek Görseller

gorsel-1.png
Büyütmek için tıklayın

Diğer Paylaşımlar

Veritabanı

SQLite Üretim Ortamında: Küçük ve Orta Ölçekli Projeler İçin Ne Zaman Yeterli?

SQLite Üretim Ortamında: Küçük ve Orta Ölçekli Projeler İçin Ne Zaman Yeterli? Bir web projesine başlarken neredeyse refleks hâline gelmiş b

12 Haziran 2026
Web Geliştirme

Sağlam Bir REST API Nasıl Tasarlanır?

Sağlam Bir REST API Nasıl Tasarlanır? Bir API, uygulamanızın dış dünyaya açılan kapısıdır. İyi tasarlanmış bir API'yi kullanan geliştirici,

30 Mayıs 2026
Web Geliştirme

Web Sitesi Performansını Artırmanın Yolları

Web Sitesi Performansını Artırmanın Yolları Bir web sayfasının ilk üç saniyede açılmaması, ziyaretçilerin önemli bir kısmının sekmeyi kapatm

30 Mayıs 2026
Yazılım Araçları

VS Code'da Verimliliği Artıran Kısayollar ve Eklentiler

VS Code'da Verimliliği Artıran Kısayollar ve Eklentiler Bir geliştiricinin günü editörde geçer. Editörle aranızdaki sürtünmeyi azaltmak, gün

30 Mayıs 2026

Tüm paylaşımları görüntüle →

1 / 1

CaYaDev

CaYaDev — kişisel projelerimi, kod örneklerimi ve teknoloji içeriklerimi paylaştığım platform. Geliştiriciler için kaynak ve ilham kaynağı.

Hızlı Bağlantılar

  • CaYaDev Projeleri
  • CaYaDev Paylaşımları
  • Destek
  • Hakkımızda

İletişim

  • İletişim
  • Gizlilik Politikası
  • Kullanım Şartları
  • Sorumluluk Reddi

CaYaDev Topluluğu

CaYaDev ile geliştirici topluluğuna katılın ve projelerimizden ilham alın.

Uygulama Portalı

© 2026 CaYaDev. Tüm hakları saklıdır.