Oturum açmış bir kullanıcının tarayıcısı, başka bir siteden gönderilen istekte çerezleri otomatik taşıyabilir. Bu nedenle parola değiştirme, e-posta güncelleme veya silme gibi durum değiştiren formlarda yalnızca oturum kontrolü yeterli değildir. PHP ile oturum tabanlı bir CSRF token üretip formda göndermek ve isteği işlerken doğrulamak gerekir.
Token, kullanıcı oturumuna bağlı ve tahmin edilemez olmalıdır. Örnekte token her oturum için oluşturuluyor; aynı token, oturum sürdüğü müddetçe birden fazla form gönderiminde kullanılabilir.
Uygulama örneği
Formu göstermeden önce oturumu başlatıp token oluşturun:
<?php
session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
?>
<form method="post" action="/account/email-update.php">
<input type="hidden" name="csrf_token"
value="<?= htmlspecialchars($_SESSION['csrf_token'], ENT_QUOTES, 'UTF-8') ?>">
<label for="email">Yeni e-posta</label>
<input id="email" name="email" type="email" required>
<button type="submit">Güncelle</button>
</form>
İsteği işleyen dosyada tokenı güvenli karşılaştırmayla kontrol edin. Eksik veya yanlış token durumunda işlemi veritabanına uygulamadan sonlandırın:
<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit('Yalnızca POST destekleniyor.');
}
$sessionToken = $_SESSION['csrf_token'] ?? '';
$formToken = $_POST['csrf_token'] ?? '';
if (!is_string($formToken) ||
$sessionToken === '' ||
!hash_equals($sessionToken, $formToken)) {
http_response_code(403);
exit('Geçersiz istek.');
}
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if ($email === false || $email === null) {
http_response_code(422);
exit('Geçerli bir e-posta adresi girin.');
}
// Burada, yetkilendirme kontrolünden sonra hazırlanmış bir PDO sorgusu kullanın.
// Örnek: UPDATE ... WHERE user_id = :user_id
Kontrol listesi ve test
- Tokenı PHP'nin fonksiyonuyla üretin; sabit veya tahmin edilebilir değer kullanmayın.
random_bytes() - Tokenı HTML çıktısına yazarken kullanın.
htmlspecialchars() - Karşılaştırmada kullanın.
===2025code] yerine [code]hash_equals() - CSRF kontrolünden sonra ayrıca mevcut oturumun yetkisini ve hedef kaydın kullanıcıya ait olduğunu doğrulayın. CSRF tokenı yetkilendirme yerine geçmez.
- Veritabanı işlemlerinde parametreli PDO sorgusu kullanın.
csrf_token
