Express.js Uygulamanızı Güvene Almak: Oturumlar, CSRF ve Hız Sınırlama
C
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.

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: Expressbaş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.
Ek Görseller
Diğer Paylaşımlar
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ştirmeSağ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ştirmeWeb 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