Arif

WFN Üye
Konular
646
Mesajlar
646
Çözüm
0
Ticaret Puanı
0
Üyelik
24 Gün
Konum
Bilecik
Web Sitesi
Var
Alanı
SEO Uzmanı
1/1
Konu sahibi
Form verisini doğrulamak için gönderilen değeri önce ham hâliyle alın, boşluk ve biçim kontrollerini uygulayın, geçersiz durumda kullanıcıya hata gösterin; doğrulama başarılıysa değeri beklenen türde işleyip veritabanına parametreli sorguyla kaydedin. Doğrulama, kullanıcının gönderdiği verinin beklenen kurallara uyup uymadığını kontrol eder; tek başına veriyi güvenli hâle getirmez veya kötü amaçlı içeriği HTML içinde güvenle göstermeyi sağlamaz.

Form doğrulamasının temel akışı​


Bir formu doğrularken kontrolü yalnızca HTML tarafındaki required, type="email" veya minlength gibi özniteliklere bırakmayın. Tarayıcıdaki kontroller kullanıcı tarafından devre dışı bırakılabilir veya istek doğrudan gönderilebilir. Bu nedenle asıl doğrulama PHP tarafında, form gönderildikten sonra yapılmalıdır.

İşlem sırası genellikle şöyledir:
  1. İsteğin gerçekten POST olup olmadığını kontrol edin.
  2. Alanları $_POST içinden alın ve bulunmayan değerleri güvenli varsayılanlarla karşılayın.
  3. Boşlukları temizleyin; ancak parola gibi anlamlı boşluk içerebilecek alanları gelişigüzel değiştirmeyin.
  4. Her alan için beklenen kuralı uygulayın.
  5. Hata varsa veriyi kaydetmeyin ve hataları formun yanında gösterin.
  6. Tüm kontroller başarılıysa veriyi beklenen türde işleyin ve parametreli sorguyla kaydedin.
Aşağıdaki örnek, ad, email ve yas alanlarını kontrol eden varsayımsal bir kayıt formunun en küçük uygulanabilir sunucu tarafı örneğidir. Kodun çalışması için PHP’nin etkin olduğu bir sunucuda form.php adıyla çalıştırabilir veya mevcut form işleyicinize uyarlayabilirsiniz.

PHP:
<?php

$errors = [];
$old = [
    'ad' => '',
    'email' => '',
    'yas' => '',
];

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $old['ad'] = trim((string) ($_POST['ad'] ?? ''));
    $old['email'] = trim((string) ($_POST['email'] ?? ''));
    $old['yas'] = trim((string) ($_POST['yas'] ?? ''));

    if ($old['ad'] === '') {
        $errors['ad'] = 'Ad alanı zorunludur.';
    } elseif (mb_strlen($old['ad']) < 2 || mb_strlen($old['ad']) > 100) {
        $errors['ad'] = 'Ad 2 ile 100 karakter arasında olmalıdır.';
    }

    if ($old['email'] === '') {
        $errors['email'] = 'E-posta alanı zorunludur.';
    } elseif (filter_var($old['email'], FILTER_VALIDATE_EMAIL) === false) {
        $errors['email'] = 'Geçerli bir e-posta adresi girin.';
    }

    $yas = filter_var(
        $old['yas'],
        FILTER_VALIDATE_INT,
        ['options' => ['min_range' => 18, 'max_range' => 120]]
    );

    if ($yas === false) {
        $errors['yas'] = 'Yaş 18 ile 120 arasında tam sayı olmalıdır.';
    }

    if ($errors === []) {
        // Veritabanına kayıt yapılacaksa PDO ve parametreli sorgu kullanın.
        // Örnek işlem:
        // $stmt = $pdo->prepare(
        //     'INSERT INTO kullanicilar (ad, email, yas) VALUES (:ad, :email, :yas)'
        // );
        // $stmt->execute([
        //     ':ad' => $old['ad'],
        //     ':email' => $old['email'],
        //     ':yas' => $yas,
        // ]);

        echo 'Form verisi doğrulandı.';
    }
}
?>

<form method="post">
    <label>
        Ad
        <input type="text" name="ad" value="<?= htmlspecialchars($old['ad'], ENT_QUOTES, 'UTF-8') ?>">
    </label>
    <?php if (isset($errors['ad'])): ?>
        <p><?= htmlspecialchars($errors['ad'], ENT_QUOTES, 'UTF-8') ?></p>
    <?php endif; ?>

    <label>
        E-posta
        <input type="email" name="email" value="<?= htmlspecialchars($old['email'], ENT_QUOTES, 'UTF-8') ?>">
    </label>
    <?php if (isset($errors['email'])): ?>
        <p><?= htmlspecialchars($errors['email'], ENT_QUOTES, 'UTF-8') ?></p>
    <?php endif; ?>

    <label>
        Yaş
        <input type="number" name="yas" value="<?= htmlspecialchars($old['yas'], ENT_QUOTES, 'UTF-8') ?>">
    </label>
    <?php if (isset($errors['yas'])): ?>
        <p><?= htmlspecialchars($errors['yas'], ENT_QUOTES, 'UTF-8') ?></p>
    <?php endif; ?>

    <button type="submit">Gönder</button>
</form>

Form ilk kez açıldığında istek GET olduğu için doğrulama çalışmaz ve boş alanlar gösterilir. Kullanıcı gönder düğmesine bastığında istek POST olur; PHP alanları kontrol eder. Hata oluşursa $errors dizisi boş kalmaz, kayıt işlemi yapılmaz ve $old içindeki değerler forma geri yazılarak kullanıcının tüm alanları yeniden doldurması engellenir. Hata yoksa $errors === [] koşulu sağlanır ve kayıt adımına geçilebilir.

Önemli: Formda kullanıcıdan gelen metni tekrar gösterirken htmlspecialchars() kullanın. Bu işlem HTML çıktısında özel karakterlerin yorumlanmasını önler. Ancak veriyi veritabanına kaydetmek için HTML kaçışlaması değil, parametreli sorgu kullanılır. Verinin hangi bağlamda kullanılacağına göre uygun çıktı kodlaması ayrıca yapılmalıdır.

Alan türüne göre doğru kontrolü seçin​


Her alanı aynı yöntemle kontrol etmek doğru sonuç vermez. Örneğin bir e-posta adresi için metin karşılaştırması yapmak yerine FILTER_VALIDATE_EMAIL, tam sayı için ise FILTER_VALIDATE_INT kullanılabilir. Sayısal alanı yalnızca is_numeric() ile kontrol etmek, ondalık veya beklenmeyen sayı biçimlerini kabul edebilir; alan gerçekten tam sayı gerektiriyorsa tam sayı doğrulaması daha uygundur.
AlanKontrolBaşarısız sonuç
Zorunlu metinBoş olup olmadığını ve uzunluk sınırını kontrol edin.Alan boş veya izin verilen uzunluk dışında demektir.
E-postaFILTER_VALIDATE_EMAIL kullanın.Biçim geçerli görünmüyor; bu, adresin gerçekten kullanıldığını kanıtlamaz.
Tam sayıFILTER_VALIDATE_INT ve aralık seçeneklerini kullanın.Değer tam sayı değildir veya izin verilen aralık dışındadır.
Seçim alanıDeğerin izin verilen seçenekler listesinde olup olmadığını kontrol edin.Kullanıcı listede bulunmayan bir değer göndermiştir.
ParolaUzunluk ve parola politikasını kontrol edin; saklarken password_hash() kullanın.Parola kuralları karşılanmamıştır.
Tablodaki kontroller yalnızca biçim ve kural uygunluğunu gösterir. Örneğin FILTER_VALIDATE_EMAIL başarılı olduğunda adresin gerçekten var olduğu veya o adrese erişimin kullanıcıya ait olduğu kanıtlanmaz. Böyle bir gereksinim varsa doğrulama e-postası gönderip kullanıcının bağlantıyı açmasını beklemek gerekir.

Zorunlu alan ve boşluk kontrolü​


Metin alanlarında genellikle trim() kullanmak uygundur. Böylece yalnızca boşluklardan oluşan bir giriş boş kabul edilir. Ancak parola veya biçimi anlamlı olan başka bir değer için baştaki ve sondaki boşlukları otomatik silmek, kullanıcının gönderdiği veriyi değiştirebilir. Her alanın iş kuralına göre karar verin.

E-posta kontrolü biçim kontrolüdür​


filter_var($email, FILTER_VALIDATE_EMAIL) e-posta adresinin beklenen biçime uygun olup olmadığını denetler. Sonuç false ise formu kaydetmeyin. Sonuç başarılıysa adresi normalleştirme, daha önce kayıtlı olup olmadığını kontrol etme veya doğrulama e-postası gönderme gibi uygulama kurallarını ayrıca yürütün.

Seçim alanlarında kullanıcıdan gelen değere güvenmeyin​


Örneğin bir kullanıcı rolü yalnızca editor veya author olabiliyorsa, gelen değeri doğrudan kaydetmek yerine izin verilen listeyle karşılaştırın:

PHP:
$izinVerilenRoller = ['editor', 'author'];
$rol = (string) ($_POST['rol'] ?? '');

if (!in_array($rol, $izinVerilenRoller, true)) {
    $errors['rol'] = 'Geçersiz rol seçildi.';
}

Buradaki üçüncü parametrenin true olması, karşılaştırmanın tür duyarlı yapılmasını sağlar. Böylece sayı ile metin arasında beklenmeyen otomatik dönüşümlerden kaçınılır.

Doğrulama, temizleme ve güvenliği birbirine karıştırmayın​


Doğrulama, “Bu değer kurala uyuyor mu?” sorusunu yanıtlar. Temizleme veya dönüştürme ise değeri başka bir biçime çevirebilir. Örneğin bir telefon numarasından boşlukları kaldırmak biçim dönüştürme olabilir; fakat bu işlem numaranın gerçekten kime ait olduğunu kanıtlamaz.

Kullanıcı girdisini veritabanına eklerken SQL sorgusunu metin birleştirmeyle oluşturmayın. PDO::prepare() ve execute() ile parametreli sorgu kullanın. Kullanıcı girdisini HTML içinde gösterirken htmlspecialchars() uygulayın. Parolaları düz metin olarak saklamayın; password_hash() ile özetleyin ve giriş sırasında password_verify() kullanın.

Ayrıca formun yaptığı işlem oturum açmış kullanıcı adına değişiklik yapıyor, para hareketi oluşturuyor veya silme işlemi gerçekleştiriyorsa CSRF koruması ekleyin. CSRF koruması form alanının geçerli olup olmadığını değil, isteğin beklenen uygulama oturumundan gelip gelmediğini kontrol eder; bu nedenle normal alan doğrulamasının yerine geçmez.

Hata durumunu nasıl yorumlamalısınız?​


Bir alan için hata üretildiğinde o alanın değeri uygulamanın beklediği kurala uymamıştır. Bu, kullanıcının kötü niyetli olduğunu kanıtlamaz; değer yanlış yazılmış, eksik gönderilmiş veya formun dışında hazırlanmış olabilir. Hata mesajını kullanıcıya anlaşılır gösterin, fakat veritabanı veya iç sistem ayrıntılarını açığa çıkarmayın.

Tüm alanlar başarılı görünüyorsa bu yalnızca gönderilen verinin tanımladığınız biçim kurallarını geçtiğini gösterir. E-posta adresinin varlığı, kullanıcının yetkisi, kaydın benzersiz olması veya veritabanı işleminin başarılı olması ayrıca kontrol edilmelidir. Örneğin e-posta alanı geçerli biçimde olsa bile aynı adres daha önce kayıtlı olabilir; bu durumda benzersizlik kuralını veritabanında da tanımlayıp oluşabilecek çakışmayı işlem sonucu üzerinden ele alın.

Kayıt işleminden sonra başarı mesajı gösteriyorsanız, mesajı yalnızca PHP doğrulaması başarılı olduğu için vermeyin. Veritabanı execute() sonucunu, oluşabilecek istisnaları ve gerekiyorsa işlem taahhüdünü kontrol edin. Başarılı doğrulama ile başarılı kayıt aynı sonuç değildir.

Üretim ortamında eklemeniz gereken kontroller​


Gerçek bir uygulamada alan kurallarını formun HTML kısmında da belirtmek kullanıcıya erken geri bildirim sağlar; fakat sunucu tarafındaki kontroller yine zorunludur. Özellikle şu ayrımları koruyun:
  • Formdaki required özniteliği yalnızca tarayıcı tarafı kolaylığıdır; güvenlik sınırı değildir.
  • Kullanıcı yetkisini, gönderilen user_id veya rol alanından çıkarmayın; yetkiyi oturumdaki kullanıcı ve sunucu tarafındaki kurallarla belirleyin.
  • Dosya yüklemelerinde yalnızca dosya uzantısını kontrol etmeyin; boyut, hata kodu, MIME türü ve dosyanın kaydedileceği konum ayrıca ele alınmalıdır.
  • Hataları kullanıcıya gösterirken SQL sorgusu, dosya yolu veya sunucu yapılandırması gibi iç ayrıntıları göstermeyin.
  • Form tekrar gönderilebildiği için kritik kayıtlarda işlem kimliği veya uygun bir tekrar gönderim kontrolü düşünün.
Bu yaklaşımın sonunda beklenen sonuç şudur: Geçersiz veri kaydedilmeden kullanıcıya hangi alanı nasıl düzeltmesi gerektiği gösterilir; geçerli veri ise türü ve bağlamı dikkate alınarak işlenir. Doğrulama başarılı olsa bile veritabanı sorgusu, yetki kontrolü, çıktı kodlaması ve gerekiyorsa CSRF koruması ayrı güvenlik adımları olarak uygulanmalıdır.

Sık sorulan sorular​

Form doğrulamasını yalnızca JavaScript ile yapmak yeterli mi?​

Hayır. JavaScript kullanıcıya hızlı geri bildirim verir, ancak istek JavaScript çalıştırılmadan da gönderilebilir. Bu nedenle aynı kurallar PHP tarafında yeniden kontrol edilmelidir.

Doğrulama hatası varsa form alanlarını boşaltmalı mıyım?​

Genellikle hayır. Kullanıcının geçerli alanlarını htmlspecialchars() ile güvenli biçimde tekrar gösterin ve yalnızca parolalar gibi hassas alanları yeniden doldurmayın. Hata mesajı ilgili alanın yanında açıkça görünmelidir.

PHP’de gelen veriyi otomatik olarak güvenli hâle getiren tek bir fonksiyon var mı?​

Yoktur. Veritabanı için parametreli sorgu, HTML çıktısı için htmlspecialchars(), parola için password_hash() ve iş kuralı için alanın türüne uygun doğrulama gerekir. Bir bağlamda kullanılan temizleme işlemi başka bir bağlamın güvenlik çözümü değildir.

E-posta doğrulaması başarılıysa e-posta adresini kabul etmeli miyim?​

Biçim açısından kabul edebilirsiniz; ancak adresin gerçekten var olduğunu veya kullanıcıya ait olduğunu varsaymamalısınız. Kullanıcı hesabı ya da kritik bildirim akışında doğrulama bağlantısı göndererek sahipliği ayrıca onaylatın.
 

Sende şimdi bize katılmak ister misin?

Kayıt ol

Bize katılım kolay ve ücretsizdir!

Foruma git ?

Bu konuyu görüntüleyen kullanıcılar

Bu konuyu şu anda görüntüleyen üye bulunmuyor.
Robotlar:
  • Anthropic