Süreçlerinize uygun yazılımı birlikte planlayalım. Demo ve teklif için arayın: +90 546 737 48 29

TR EN DE

Giriş ve oturum güvenliği

Web Sitesi Güvenliği · Hazırlayan: BYK Yazılım Destek Ekibi · Güncelleme: 04.10.2026

Giriş ekranı sitenizin kapısıdır; oturum ise içeri giren kişinin kimliğini sonraki her istekte taşıyan anahtardır. Bu ikisinden biri zayıfsa, kodun geri kalanı ne kadar sağlam olursa olsun hesaplar ele geçirilebilir. Yaygın sorunlar bellidir: zayıf yöntemle saklanan parolalar, sınırsız parola denemesi, girişte yenilenmeyen oturum kimliği, korumasız çerezler ve yalnızca menüde gizlenen ama sunucuda denetlenmeyen yetkiler.

Bu rehber, PHP ile yazılmış bir sitede giriş ve oturum katmanının nasıl doğru kurulacağını anlatır. Kullanıcı tarafındaki önlemler için Güçlü şifre ve şifre yöneticisi rehberine bakın.

Dört temel

  1. Parolayı değil, karmasını saklayın

    Parolalar veritabanında asla düz metin ya da geri çözülebilir biçimde saklanmaz. MD5, SHA-1 ve tuzsuz SHA-256 gibi hızlı özet işlevleri de parola saklamak için uygun değildir; hızlı oldukları için sızan bir veritabanındaki parolalar kısa sürede denenebilir. PHP'nin password_hash işlevi, parola için tasarlanmış yavaş bir algoritma kullanır ve tuzu kendiliğinden üretir.

    <?php
    // Kayıt ya da parola değişikliği
    $karma = password_hash($parola, PASSWORD_DEFAULT);
    // $karma veritabanına yazılır (kolon: VARCHAR(255))
    
    // Giriş
    if (password_verify($girilenParola, $kullanici['parola_karma'])) {
        // Algoritma ya da maliyet değiştiyse karmayı güncelle
        if (password_needs_rehash($kullanici['parola_karma'], PASSWORD_DEFAULT)) {
            $yeni = password_hash($girilenParola, PASSWORD_DEFAULT);
            $pdo->prepare('UPDATE kullanicilar SET parola_karma = ? WHERE id = ?')
                ->execute([$yeni, $kullanici['id']]);
        }
    }
    Karşılaştırma: düz metin, MD5 ve SHA-1 ile parola saklamak yanlış; password_hash ve password_verify doğru
  2. Deneme sayısını sınırlayın

    Sınırsız deneme hakkı, parola tahminini mümkün kılar. Hem hesap hem IP adresi bazında başarısız denemeleri sayın; belirli bir sayıdan sonra bekleme süresi uygulayın ve süreyi kademeli artırın. Hata mesajı, kullanıcı adının mı parolanın mı yanlış olduğunu belli etmemelidir.

    Akış şeması: giriş denemesi, deneme sayısı kontrolü, parola doğrulama, oturum kimliğini yenileme, yetki
  3. Girişte oturum kimliğini yenileyin

    Oturum sabitleme, kullanıcının giriş yapmadan önce sahip olduğu oturum kimliğinin girişten sonra da geçerli kalmasından doğar; kimliği önceden bilen biri, kullanıcı giriş yaptığında aynı oturumu kullanabilir. Çözüm basittir: giriş başarılı olduğunda ve yetki düzeyi değiştiğinde oturum kimliğini yenileyin.

    Şema: oturum çerezi bayrakları; Secure, HttpOnly, SameSite ve girişte yenilenen oturum kimliği
  4. Yetkiyi her istekte sunucuda denetleyin

    Bir düğmeyi ya da menü öğesini gizlemek yetki kontrolü değildir; adresi bilen herkes isteği doğrudan gönderebilir. Her sayfa ve her işlem, sunucuda önce oturumun geçerli olduğunu, sonra kullanıcının o işlemi o kayıt üzerinde yapmaya yetkili olduğunu denetlemelidir.

    Karşılaştırma: yalnız menüyü gizlemek yanlış; her istekte sunucuda oturum, rol ve kayıt sahipliği kontrolü doğru

Belirtiler: nasıl fark edilir?

  • Veritabanında: Parola kolonunda 32 ya da 40 karakterlik onaltılık değerler (MD5, SHA-1) ya da okunabilir parolalar görüyorsanız saklama yöntemi zayıftır. password_hash çıktısı $2y$ ya da $argon2 ile başlar.
  • Günlüklerde: Giriş adresine kısa sürede çok sayıda POST isteği; farklı kullanıcı adlarıyla art arda denemeler; alışılmadık ülke ya da saatlerden başarılı girişler.
  • Tarayıcıda: Geliştirici araçlarında oturum çerezinin Secure, HttpOnly ve SameSite bayrakları yoksa; giriş öncesi ve sonrası oturum kimliği aynıysa.
  • Uygulamada: Oturumu kapattıktan sonra yönetim sayfasının adresi doğrudan yazıldığında içerik görünüyorsa; adresteki kayıt numarasını değiştirince başka kullanıcının kaydı açılıyorsa.

Güvenli giriş akışı

Aşağıdaki örnek; deneme sınırını, parolanın doğrulanmasını, gerektiğinde karmanın güncellenmesini ve oturum kimliğinin yenilenmesini bir arada gösterir.

<?php
$eposta = strtolower(trim((string) ($_POST['eposta'] ?? '')));
$parola = (string) ($_POST['parola'] ?? '');
$ip     = $_SERVER['REMOTE_ADDR'] ?? '';

if (cokFazlaDeneme($pdo, $eposta, $ip)) {
    http_response_code(429);
    echo 'Çok fazla deneme yapıldı. Lütfen 15 dakika sonra tekrar deneyin.';
    return;
}

$sorgu = $pdo->prepare('SELECT id, parola_karma, rol FROM kullanicilar WHERE eposta = ? AND aktif = 1');
$sorgu->execute([$eposta]);
$kullanici = $sorgu->fetch();

// Kullanıcı yoksa da bir doğrulama yap: yanıt süresi kullanıcının varlığını ele vermesin.
// SAHTE_KARMA: yapılandırmada bir kez password_hash() ile üretilip sabit olarak saklanan değer
$karma = $kullanici ? $kullanici['parola_karma'] : SAHTE_KARMA;
$dogru = password_verify($parola, $karma) && $kullanici !== false;

if (!$dogru) {
    denemeKaydet($pdo, $eposta, $ip);
    echo 'E-posta ya da parola hatalı.';
    return;
}

session_regenerate_id(true);               // oturum sabitlemeye karşı
$_SESSION['kullanici_id'] = (int) $kullanici['id'];
$_SESSION['rol']          = $kullanici['rol'];
$_SESSION['son_islem']    = time();
$_SESSION['csrf']         = bin2hex(random_bytes(32));
  • Kullanıcı bulunamadığında da bir karma doğrulaması yapılır; böylece yanıt süresinden kullanıcının var olup olmadığı anlaşılmaz.
  • Hata mesajı tek ve geneldir: "E-posta ya da parola hatalı."
  • Kalıcı hesap kilitleme yerine süreli bekleme tercih edin; aksi hâlde başkası kasıtlı hatalı denemelerle kullanıcıların hesabını kilitleyebilir.
  • Giriş formu CSRF belirteci taşımalıdır.

Deneme sayacı için basit bir tablo yeterlidir:

<?php
// Tablo: giris_denemeleri (eposta VARCHAR(190), ip VARCHAR(45), zaman DATETIME, INDEX(eposta), INDEX(ip))
function cokFazlaDeneme(PDO $pdo, string $eposta, string $ip): bool
{
    $sorgu = $pdo->prepare(
        'SELECT COUNT(*) FROM giris_denemeleri
         WHERE (eposta = ? OR ip = ?) AND zaman > (NOW() - INTERVAL 15 MINUTE)'
    );
    $sorgu->execute([$eposta, $ip]);
    return (int) $sorgu->fetchColumn() >= 5;
}

function denemeKaydet(PDO $pdo, string $eposta, string $ip): void
{
    $pdo->prepare('INSERT INTO giris_denemeleri (eposta, ip, zaman) VALUES (?, ?, NOW())')
        ->execute([$eposta, $ip]);
}

Eski karma yönteminden geçiş

Mevcut sitede parolalar MD5 ya da SHA-1 ile saklanıyorsa kullanıcılara parola sıfırlatmadan geçiş yapılabilir: kullanıcı giriş yaptığında parola eski yöntemle doğrulanır, doğruysa aynı anda password_hash ile yeniden karmalanıp kaydedilir. Eski karmalar veritabanında kaldığı sürece risk sürdüğünden, belirli bir süre sonra hâlâ geçiş yapmamış hesaplar için parola sıfırlama zorunlu tutulmalıdır.

Oturum ayarları

Oturum çerezinin bayraklarını ve oturum davranışını session_start çağrısından önce ayarlayın.

<?php
ini_set('session.use_strict_mode', '1');   // sunucunun üretmediği kimlikleri reddet
ini_set('session.use_only_cookies', '1');  // kimlik adreste taşınmaz

session_set_cookie_params([
    'lifetime' => 0,          // tarayıcı kapanınca biter
    'path'     => '/',
    'secure'   => true,
    'httponly' => true,
    'samesite' => 'Lax',
]);
session_start();

// Hareketsizlik zaman aşımı: 30 dakika
$sure = 30 * 60;
if (isset($_SESSION['son_islem']) && time() - $_SESSION['son_islem'] > $sure) {
    $_SESSION = [];
    session_destroy();
    header('Location: giris?oturum=doldu');
    return;
}
$_SESSION['son_islem'] = time();
  • Secure: Çerez yalnızca HTTPS üzerinden gönderilir.
  • HttpOnly: JavaScript çerezi okuyamaz; XSS durumunda çerezin çalınmasını zorlaştırır.
  • SameSite: Başka sitelerden başlatılan isteklerde çerezin gönderilmesini sınırlar.
  • Katı kip (strict mode): Sunucunun üretmediği oturum kimliklerini reddeder.
  • Zaman aşımı: Belirli süre işlem yapılmayan oturumu sonlandırın; yönetim panellerinde süreyi kısa tutun.
  • Oturum kimliğini asla adrese (URL) koymayın.

Çıkışta oturumu gerçekten yok edin:

<?php
session_start();
$_SESSION = [];
if (ini_get('session.use_cookies')) {
    $p = session_get_cookie_params();
    setcookie(session_name(), '', [
        'expires'  => time() - 3600,
        'path'     => $p['path'],
        'domain'   => $p['domain'],
        'secure'   => $p['secure'],
        'httponly' => $p['httponly'],
        'samesite' => $p['samesite'] ?: 'Lax',
    ]);
}
session_destroy();
header('Location: giris');

Her istekte yetki kontrolü

Yetki kontrolünü her sayfanın başında çağrılan ortak bir işlevde toplayın. İki ayrı soru vardır: kullanıcı bu tür işlemi yapabilir mi (rol) ve bu kayıt ona mı ait (sahiplik)?

<?php
// Her yönetim sayfasının başında çağrılır
function yetkiIste(string $rol): void
{
    if (empty($_SESSION['kullanici_id'])) {
        header('Location: giris');
        exit;
    }
    if (($_SESSION['rol'] ?? '') !== $rol) {
        http_response_code(403);
        echo 'Bu sayfayı görüntüleme yetkiniz yok.';
        exit;
    }
}

// Kayıt sahipliği: sorguya oturumdaki kullanıcı kimliği de eklenir
$sorgu = $pdo->prepare('SELECT * FROM siparisler WHERE id = ? AND kullanici_id = ?');
$sorgu->execute([(int) ($_GET['id'] ?? 0), $_SESSION['kullanici_id']]);
$siparis = $sorgu->fetch();
if (!$siparis) {
    http_response_code(404);
    echo 'Sipariş bulunamadı.';
    return;
}

Adresteki ya da formdaki kayıt numarasına güvenmeyin; sorguya her zaman oturumdaki kullanıcı kimliğini de ekleyin. Erişim denetimi hataları, OWASP Top 10 listesinin en üst sıralarındaki risklerdendir.

Yönetim panelini ek katmanlarla koruyun

  • İki adımlı doğrulama: Yönetici hesaplarında zorunlu tutun. Kullanıcı tarafı için İki adımlı doğrulama rehberine bakın.
  • IP kısıtı: Panele yalnızca ofisinizin sabit IP adresinden ya da VPN üzerinden erişiliyorsa, panel klasörünü IP ile sınırlayın.
  • Ek parola katmanı: Sabit IP yoksa panel klasörüne sunucu düzeyinde ikinci bir parola (HTTP temel kimlik doğrulaması) eklenebilir.
  • Panel adresi: Tahmin edilmesi kolay olmayan bir adres otomatik taramaların gürültüsünü azaltır; ancak tek başına koruma değildir.
  • Kişiye özel hesaplar: Ortak "admin" hesabı kullanmayın; her yöneticinin kendi hesabı olsun ve yapılan işlemler kayıt altına alınsın.
# yonetim/.htaccess : panele yalnız belirli IP adreslerinden erişim
# (203.0.113.10 örnek adrestir; kendi sabit IP adresinizi yazın)
Require ip 203.0.113.10

# Sabit IP yoksa: sunucu düzeyinde ikinci parola katmanı
# AuthType Basic
# AuthName "Yonetim"
# AuthUserFile /home/kullanici/.htpasswd
# Require valid-user

Parola sıfırlama

  • Sıfırlama bağlantısındaki belirteç rastgele (random_bytes), tek kullanımlık ve kısa ömürlü olmalı; veritabanında karması saklanmalıdır.
  • "Bu e-posta kayıtlı değil" demeyin; her durumda aynı mesajı gösterin: "Adres kayıtlıysa sıfırlama bağlantısı gönderildi."
  • Parola değiştiğinde kullanıcının diğer açık oturumlarını sonlandırın ve bilgilendirme e-postası gönderin.
  • Yeni parolayı e-postayla göndermeyin; kullanıcı kendisi belirlesin.
  • Parola kurallarında uzunluğu öne çıkarın; en az 12 karakter isteyin ve çok yaygın parolaları reddedin.

Kontrol listesi

  • Parolalar password_hash ile saklanıyor; eski karmalar için geçiş planı var.
  • Giriş denemeleri hesap ve IP bazında sınırlı; hata mesajı genel.
  • Giriş başarılı olunca session_regenerate_id(true) çağrılıyor.
  • Oturum çerezi Secure, HttpOnly ve SameSite bayraklı; katı kip açık.
  • Hareketsizlik zaman aşımı var; çıkış oturumu yok ediyor.
  • Her sayfa ve işlem sunucuda oturum, rol ve kayıt sahipliği denetliyor.
  • Yönetici hesaplarında iki adımlı doğrulama; panelde IP kısıtı ya da ek parola katmanı.
  • Parola sıfırlama belirteci tek kullanımlık ve süreli.
  • Başarılı ve başarısız girişler günlüğe yazılıyor.

Sık sorulan sorular

PASSWORD_DEFAULT hangi algoritmayı kullanır?

PHP sürümüne göre önerilen algoritmayı seçer (güncel sürümlerde bcrypt). Algoritma ileride değişirse password_needs_rehash ile kullanıcının bir sonraki girişinde karma kendiliğinden güncellenir. Bu yüzden kolonu VARCHAR(255) tanımlayın.

Parolaya kendi tuzumu eklemeli miyim?

Hayır. password_hash her parola için rastgele tuzu kendisi üretir ve karmanın içinde saklar. Elle tuz eklemek gerekmez.

Captcha deneme sınırının yerini tutar mı?

Tek başına tutmaz. Captcha otomatik denemeleri zorlaştırır; sunucu tarafında deneme sayısını sınırlamak yine gerekir. İkisi birlikte kullanılabilir.

"Beni hatırla" özelliği güvenli mi?

Doğru yapılırsa evet: uzun ömürlü çerezde kullanıcı kimliği ya da parola değil, rastgele ve veritabanında karması tutulan bir belirteç bulunmalı; belirteç her kullanımda yenilenmeli ve parola değişince iptal edilmelidir.

BYK Yazılım Destek Ekibi
Bu rehber BYK Yazılım destek ekibi tarafından hazırlanır ve düzenli olarak gözden geçirilir. Son güncelleme: 04.10.2026.

İlgili rehberler

Web sitenizi birlikte gözden geçirelim

BYK Yazılım kurumsal web siteleri geliştirir. Sitenizle ilgili sorularınız için bize yazabilirsiniz.

Bize ulaşın Kurumsal web sitesi hizmetimiz