Web uygulamaları geliştirirken en sık ihtiyaç duyulan bileşenlerin başında kimlik doğrulama mekanizmaları gelir. Bir kullanıcının kimliğini doğrulamak, oturumunu başlatmak ve yetkisiz erişimleri engellemek, uygulamanın genel güvenliği açısından kritik bir adımdır. Bu rehberde, modern PHP standartlarına uygun, güvenli ve anlaşılır bir php giriş sistemi mimarisini sıfırdan kuracağız.
Giriş Sisteminin Çalışma Mantığı
Bir kullanıcı giriş sistemi temelde istemci ile sunucu arasındaki veri alışverişine ve bu verilerin veritabanındaki kayıtlarla karşılaştırılmasına dayanır. Süreç şu temel adımlardan oluşur:
- Kullanıcı tarayıcı üzerinden kullanıcı adı ve parolasını bir HTML formu aracılığıyla gönderir.
- Sunucu tarafındaki PHP betiği gelen verileri filtreler ve doğrular.
- Veritabanında belirtilen kullanıcı adına sahip bir kayıt olup olmadığı kontrol edilir.
- Kullanıcının girdiği parola, veritabanında saklanan karma (hash) değeri ile karşılaştırılır.
- Bilgiler doğruysa PHP oturumu (session) başlatılır ve kullanıcı yetkilendirilmiş alana yönlendirilir. Bilgiler hatalıysa kullanıcıya hata mesajı gösterilir.
Bu sürecin her aşamasında güvenlik önlemleri devrede olmalıdır. Parolaların açık metin olarak saklanmaması ve SQL enjeksiyonu açıklarının engellenmesi en öncelikli konulardır.
Veritabanı Yapısının Hazırlanması
Giriş sistemini çalıştırmak için kullanıcı bilgilerini tutacağımız bir MySQL tablosuna ihtiyacımız vardır. Bu tabloda kullanıcının benzersiz kimliği, kullanıcı adı, güvenli şekilde karma hale getirilmiş parolası ve kayıt tarihi gibi alanlar yer alır.
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Bu yapıda parola alanı VARCHAR(255) olarak tanımlanmıştır. PHP’nin sunduğu modern hash fonksiyonları uzun çıktılar ürettiği için bu alanın yeterince geniş olması zorunludur. Kısa bir alan seçilirse hash değeri kesilebilir ve kullanıcı bir daha giriş yapamaz.
Test amaçlı olarak bu tabloya komut satırından veya veritabanı yönetim aracınızdan parola karmasıyla birlikte bir kullanıcı ekleyebilirsiniz. PHP’nin password_hash() fonksiyonuyla üretilmiş bir örneği doğrudan eklemek en doğrusudur.
Güvenli Veritabanı Bağlantısı (PDO)
Veritabanı iletişimi için eskiyen fonksiyonlar yerine PHP Veri Nesneleri (PDO) kullanılmalıdır. PDO, hazırlıklı ifadeler (prepared statements) desteği sunarak SQL enjeksiyonu saldırılarını baştan engeller.
Proje dizininizde db.php adında bir dosya oluşturun ve içine şu bağlantı kodlarını ekleyin:
<?php
$host = 'localhost';
$dbname = 'test_db';
$username = 'root';
$password = '';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);
} catch (PDOException $e) {
die("Veritabanı bağlantı hatası: " . $e->getMessage());
}
Bu dosyada PDO::ATTR_ERRMODE ayarını ERRMODE_EXCEPTION yaparak olası SQL hatalarının yakalanabilmesini sağladık. ATTR_EMULATE_PREPARES değerini false yapmak ise sorguların doğrudan MySQL sunucusu tarafından yerel olarak derlenmesini sağlayarak güvenliği artırır.
Giriş Formu ve Kimlik Doğrulama Mantığı
Kullanıcıların bilgilerini gireceği arayüz ile bu bilgileri işleyecek PHP kodunu tek bir dosyada veya ayrılmış yapılarda tutabiliriz. İşleyişi net görebilmek adına login.php adında bir dosya oluşturalım.
<?php
session_start();
require_once 'db.php';
if (isset($_SESSION['user_id'])) {
header("Location: dashboard.php");
exit;
}
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$user = trim($_POST['username'] ?? '');
$pass = trim($_POST['password'] ?? '');
if (empty($user) || empty($pass)) {
$error = 'Lütfen tüm alanları doldurun.';
} else {
$stmt = $pdo->prepare("SELECT id, username, password FROM users WHERE username = :username LIMIT 1");
$stmt->execute(['username' => $user]);
$userData = $stmt->fetch();
if ($userData && password_verify($pass, $userData['password'])) {
session_regenerate_id(true);
$_SESSION['user_id'] = $userData['id'];
$_SESSION['username'] = $userData['username'];
header("Location: dashboard.php");
exit;
} else {
$error = 'Geçersiz kullanıcı adı veya parola.';
}
}
}
?>
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<title>Giriş Yap</title>
</head>
<body>
<h2>Kullanıcı Girişi</h2>
<?php if (!empty($error)): ?>
<p style="color: red;"><?php echo htmlspecialchars($error); ?></p>
<?php endif; ?>
<form action="/en/login.php/" method="POST" data-trp-original-action="login.php">
<div>
<label for="username">Kullanıcı Adı:</label><br>
<input type="text" id="username" name="username" required>
</div>
<br>
<div>
<label for="password">Parola:</label><br>
<input type="password" id="password" name="password" required>
</div>
<br>
<button type="submit">Giriş Yap</button>
<input type="hidden" name="trp-form-language" value="en"/></form>
</body>
</html>
Yukarıdaki kod bloğunda dikkat edilmesi gereken önemli noktalar bulunmaktadır:
session_start()fonksiyonu, oturum mekanizmasını başlatmak için dosyanın en başında çağrılmıştır.- Formdan gelen veriler doğrudan sorguya eklenmemiş,
:usernameparametresi ile hazırlanmış ifadeye bağlanmıştır. Bu yaklaşım SQL injection saldırılarını tamamen engeller. - Parola kontrolü için
password_verify()fonksiyonu kullanılmıştır. Bu fonksiyon girilen açık parolayı, veritabanındaki karma ile matematiksel olarak doğrular. - Doğrulama başarılı olduğunda
session_regenerate_id(true)çağrılarak oturum sabitleme (session fixation) saldırılarına karşı oturum kimliği yenilenmiştir. - Kullanıcıya gösterilen hata mesajı genel tutulmuştur. Kullanıcı adı mı yoksa parola mı hatalı belirtilmemiştir; bu durum kullanıcı adı toplama (enumeration) saldırılarını zorlaştırır.
Korumalı Sayfa: Dashboard
Giriş yapan kullanıcının görebileceği, giriş yapmamış kişilere kapalı olan sayfayı dashboard.php adıyla oluşturalım.
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit;
}
?>
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<title>Yönetim Paneli</title>
</head>
<body>
<h2>Hoş Geldin, <?php echo htmlspecialchars($_SESSION['username']); ?>!</h2>
<p>Bu alan yalnızca oturum açmış kullanıcılara açıktır.</p>
<p><a href="/en/logout.php/">Çıkış Yap</a></p>
</body>
</html>
Bu sayfada $_SESSION['user_id'] anahtarının varlığı kontrol edilir. Eğer oturum anahtarı tanımlı değilse istemci header() fonksiyonu ile anında login.php sayfasına yönlendirilir ve ardından gelen exit çağrısı sayesinde sayfanın geri kalan kodlarının çalıştırılması engellenir. Kullanıcı adını ekrana basarken htmlspecialchars() kullanarak XSS (siteler arası betik çalıştırma) açıklarının önüne geçilmiş olur.
Güvenli Çıkış İşlemi (Logout)
Kullanıcının işi bittiğinde oturumunun sonlandırılması güvenlik açısından gereklidir. logout.php dosyası oturumu tamamen temizlemek için kullanılır.
<?php
session_start();
$_SESSION = [];
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(
session_name(),
'',
time() - 42000,
$params["path"],
$params["domain"],
$params["secure"],
$params["httponly"]
);
}
session_destroy();
header("Location: login.php");
exit;
Bu dosyada yalnızca session_destroy() çağırmak yeterli olmayabilir. İstemci tarafında kalan oturum çerezini geçersiz kılmak için tarayıcı çerezi sıfırlanır ve $_SESSION dizisi boş bir diziye eşitlenir. Böylece oturum verisi hem sunucudan hem de istemciden tamamen silinir.
Sistemin Güvenliğini Artırma Yöntemleri
Hazırladığımız php giriş sistemi temel güvenlik gereksinimlerini karşılasa da canlı ortamlarda ek katmanlar eklenmelidir:
- Formlara CSRF (Cross-Site Request Forgery) jetonları ekleyerek oturumun üçüncü taraf sitelerden istismar edilmesi önlenmelidir.
- Hatalı giriş denemelerine hız sınırlaması (rate limiting) uygulanarak kaba kuvvet (brute-force) saldırıları engellenmelidir.
- Oturum çerezleri yapılandırılırken
HttpOnlyveSameSiteözellikleri aktif edilmeli, uygulamanın HTTPS üzerinden çalıştığından emin olunmalıdır.
Özet ve Sonraki Adımlar
Bu yazıda, PHP ve PDO kullanarak SQL enjeksiyonlarına karşı korumalı, parolaları modern algoritmalarla doğrulayan ve oturum güvenliğini sağlayan temel bir giriş mekanizması inşa ettik.
Bir sonraki adım olarak sisteme yeni kullanıcıların dahil olmasını sağlayacak bir kayıt olma (register) sayfası ekleyebilir, parola sıfırlama mekanizması ve iki aşamalı doğrulama (2FA) katmanları kurarak yapıyı daha ileri seviyeye taşıyabilirsiniz.


Comments
No comments yet. Write the first comment.