Bir Metin2 sunucusu açtığında oyuncuların ilk karşılaştığı kapı, web sitesindeki kayıt formudur. İyi tasarlanmış bir Metin2 register sistemi sadece bir kullanıcı adı ve şifre almakla kalmaz; girişleri doğrular, şifreyi oyunun beklediği biçimde saklar ve account tablosuna güvenli şekilde yazar. Bu yazıda PHP ve PDO ile sıfırdan çalışan, SQL injection'a kapalı bir kayıt akışı kuruyoruz.
account tablosu nasıl çalışır?
Klasik Metin2 kaynaklarında üyelik bilgileri account adlı veritabanındaki account tablosunda tutulur. Oyun çekirdeği (game ve db) giriş kontrolünü doğrudan bu tablo üzerinden yapar. İlgilendiğimiz temel sütunlar şunlardır:
login— kullanıcı adı (genelde benzersiz ve kısa).password— oyunun okuduğu şifre alanı. Klasik kaynak MySQL'inPASSWORD()fonksiyonuyla üretilen 41 karakterlik hash'i bekler.social_id— 7 haneli güvenlik kodu (ikinci şifre); karakter silme gibi işlemlerde kullanılır.emailvecreate_time— iletişim ve kayıt zamanı.
Önemli bir nokta: PASSWORD() fonksiyonu MySQL 8.0'da kaldırıldı. Çoğu Metin2 sunucusu MariaDB veya MySQL 5.x kullandığı için fonksiyon hâlâ vardır, ama versiyonunu kontrol etmen gerekir. Şifreyi oyun çekirdeğiyle aynı algoritmayla saklamak zorundasın; aksi halde web'den kayıt olan oyuncu oyuna giremez.
Güvenli veritabanı bağlantısı
Her şeyden önce PDO ile prepared statement kullan. Bu, kullanıcı girdisini sorgudan ayırarak SQL injection'ı baştan engeller. Bağlantıyı ayrı bir config.php dosyasında topla:
<?php
// config.php
$host = '127.0.0.1';
$db = 'account';
$user = 'metin2_web'; // sadece account tablosuna yetkili kullanıcı
$pass = 'GUCLU_PAROLA';
$dsn = "mysql:host=$host;dbname=$db;charset=utf8mb4";
$pdo = new PDO($dsn, $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);
Web için ayrı bir MySQL kullanıcısı oluştur ve ona yalnızca account.account üzerinde gerekli yetkileri ver. Web sunucusu ele geçirilse bile saldırgan oyun veritabanının tamamına erişemesin.
Kayıt formu ve girdi doğrulama
Basit ama yeterli bir HTML formuyla başla. Asıl iş, gelen verinin sunucu tarafında doğrulanmasıdır — istemci tarafı kontrolüne asla güvenme.
<form method="post" action="register.php">
<input name="login" placeholder="Kullanıcı adı" required>
<input name="email" type="email" placeholder="E-posta" required>
<input name="password" type="password" placeholder="Şifre" required>
<input name="password2" type="password" placeholder="Şifre (tekrar)" required>
<input type="hidden" name="csrf" value="<?= $_SESSION['csrf'] ?>">
<button type="submit">Kayıt Ol</button>
</form>
Sunucu tarafında her alanı tek tek kontrol et:
<?php
session_start();
require 'config.php';
// CSRF kontrolü
if (!hash_equals($_SESSION['csrf'] ?? '', $_POST['csrf'] ?? '')) {
http_response_code(400);
exit('Geçersiz istek.');
}
$login = trim($_POST['login'] ?? '');
$email = trim($_POST['email'] ?? '');
$pw = $_POST['password'] ?? '';
$pw2 = $_POST['password2'] ?? '';
$errors = [];
if (!preg_match('/^[a-zA-Z0-9]{4,16}$/', $login)) {
$errors[] = 'Kullanıcı adı 4-16 karakter ve sadece harf/rakam olmalı.';
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Geçerli bir e-posta gir.';
}
if (strlen($pw) < 6 || $pw !== $pw2) {
$errors[] = 'Şifre en az 6 karakter olmalı ve iki alan eşleşmeli.';
}
login alanını sıkı bir desenle sınırlamak (sadece harf ve rakam) hem oyun istemcisiyle uyum sorunlarını hem de beklenmedik karakterleri engeller.
Kullanıcı adı çakışmasını kontrol et
Aynı kullanıcı adıyla iki kez kayıt olunmasını engellemek için yazmadan önce sorgula. Burada da prepared statement kullan:
if (!$errors) {
$stmt = $pdo->prepare('SELECT id FROM account WHERE login = ? LIMIT 1');
$stmt->execute([$login]);
if ($stmt->fetch()) {
$errors[] = 'Bu kullanıcı adı zaten alınmış.';
}
}
Yine de tek savunma hattın bu olmasın: account tablosundaki login sütununa UNIQUE indeks ekle. İki istek aynı anda gelirse veritabanı seviyesindeki kısıt çift kaydı keser.
Şifreyi hashleyip account tablosuna yaz
Son adımda kaydı oluşturuyoruz. Şifreyi doğrudan SQL içinde PASSWORD() ile hashlemek, oyunun beklediği biçimi garanti eder. social_id için rastgele 7 haneli bir kod üret:
if (!$errors) {
$social = sprintf('%07d', random_int(0, 9999999));
$sql = 'INSERT INTO account (login, password, social_id, email, create_time)
VALUES (?, PASSWORD(?), ?, ?, NOW())';
$stmt = $pdo->prepare($sql);
$stmt->execute([$login, $pw, $social, $email]);
header('Location: register.php?ok=1');
exit;
}
Dikkat et: parametre olarak düz şifreyi gönderiyoruz, hash'lemeyi MySQL yapıyor. Bu sayede hem prepared statement güvenliği korunur hem de hash oyunla birebir uyumlu olur. Şifreyi PHP'de kendin hash'leyip (örneğin password_hash()) saklarsan oyun çekirdeği o değeri tanımaz — bu çok yapılan bir hatadır. password_hash()/bcrypt yalnızca oyundan bağımsız, tamamen web tabanlı bir hesap sistemi kuruyorsan mantıklıdır.
Üretime almadan önce
Kayıt akışı çalıştıktan sonra şu güvenlik katmanlarını ekle:
- Rate limit: aynı IP'den dakikada birkaç kayıttan fazlasını engelle; bot kaydını zorlaştırır.
- HTTPS zorunlu: şifreler düz metin gitmesin.
- CAPTCHA: otomatik kayıtlara karşı hCaptcha/reCAPTCHA ekle.
- Hata maskeleme: kullanıcıya teknik hata gösterme, ayrıntıları sunucu loguna yaz.
Sık Sorulan Sorular
Şifreyi neden PHP'de değil MySQL'de hashliyorum?
Çünkü Metin2 oyun çekirdeği girişte şifreyi MySQL'in PASSWORD() fonksiyonunun ürettiği hash ile karşılaştırır. Aynı algoritmayı kullanmazsan web'den kayıt olan oyuncu oyuna giremez. Web ile oyun ayrı sistemler değilse uyum şart.
PASSWORD() fonksiyonu sunucumda yoksa ne yaparım?
MySQL 8.0 bu fonksiyonu kaldırdı. Çözüm, çoğu Metin2 kurulumunun zaten kullandığı MariaDB veya MySQL 5.7'ye geçmek ya da çekirdeğin desteklediği hash'i (bazı sürümlerde modifiye edilmiş şemalar) eşlemektir. Her durumda referans, oyun çekirdeğinin auth kodudur.
social_id ne işe yarar, boş bırakabilir miyim?
social_id oyun içi güvenlik kodudur (ikinci şifre) ve karakter silme gibi kritik işlemlerde sorulur. Boş bırakmak yerine kayıt sırasında rastgele bir değer atayıp oyuncunun panelden değiştirmesine izin vermek en güvenlisidir.
Metin2 sunucun için güvenli bir register ve hesap paneli mi lazım? Doğrulama, e-posta onayı ve panel entegrasyonuyla baştan sona kurabilirim — benimle iletişime geç.