Limit=1, Uzun Session (5 Yil), auth_session_lifetime Setting
Device = Tarayici Instance (Browser)
Session veya IP degil, tarayici bazli sayim yapiliyor:
mzb_login_token cookie eslesiyorLimit=1 demek: Kullanici ayni anda sadece 1 tarayicida aktif olabilir. Farkli tarayicidan giris yaparsa eski tarayici otomatik atilir (LIFO).
public function registerSession(User $user)
{
// ❌ Cookie kontrolu YOK!
$loginToken = bin2hex(random_bytes(32));
// Sonuc: Ayni tarayici bile yeni cihaz!
}
public function registerSession(User $user)
{
// ✅ 1. Cookie kontrol et
$existingToken = request()->cookie('mzb_login_token');
if ($existingToken) {
$existing = DB::table('user_active_sessions')
->where('login_token', $existingToken)->first();
if ($existing) {
// AYNI TARAYICI - guncelle
$existing->update([...]);
return; // YENi TOKEN OLUSTURMA!
}
}
// ✅ 2. LIFO - eski session'lari sil
// ✅ 3. Yeni token olustur
}
DeviceService.php:50-144
Admin paneldeki "Oturum Suresi (dakika)" alanina yazilan deger:
10080 = 1 hafta43200 = 1 ay525600 = 1 yil2628000 = 5 yil$lifetime = (int) setting('auth_session_lifetime', 10080);
$expiresAt = now()->addMinutes($lifetime);
cookie('mzb_login_token', $token, $lifetime);
mzb_login_token olusur// DOGRU AKIS:
$existingToken = request()->cookie('mzb_login_token');
if ($existingToken) {
$existing = DB::table('user_active_sessions')
->where('user_id', $user->id)
->where('login_token', $existingToken)
->first();
if ($existing) {
// AYNI TARAYICI - sadece guncelle
$existing->update([
'session_id' => session()->getId(),
'last_activity' => now()
]);
return; // Yeni token OLUSTURMA!
}
}
// FARKLI TARAYICI - LIFO uygula, eski at
// HATALI: DB::delete() ama Redis hala acik! // DOGRU: DB + Redis + Cache hepsi atomic silinmeli
enforceDeviceLimit() yorum satirinda. Farkli tarayicidan giris yapilinca eski oturum kapatilmiyor.
// DeviceService.php:92-94 // $this->enforceDeviceLimit($user, $sessionId); // YORUM SATIRINDA!
// Cozum: Redis distributed lock
$lock = Cache::lock("user_login:{$userId}", 10);
// Cozum: session_id yerine login_token kullan // login_token degismiyor, guvenilir identifier
App\Services\Auth\DeviceService (ESKi - sessions tablosu) ve Modules\Muzibu\...\DeviceService (YENi - user_active_sessions) karisik.
SongStreamController device limit kontrolu yorum satirinda. Atilan cihaz muzik dinleyebiliyor.
| Dosya | Aksiyon |
|---|---|
| App\Services\Auth\DeviceService.php | SIL |
| CheckDeviceLimit middleware | YENIDEN YAZ |
| handlePostLoginDeviceLimit() | SIL (bos metod) |
| updateSessionActivity() tehlikeli kisim | SIL |
| Device selection modal (login.blade) | KALDIR (LIFO ile gereksiz) |
/**
* Device = Browser (Tarayici)
* - Ayni tarayici = ayni cihaz (cookie ile tespit)
* - Farkli tarayici = farkli cihaz (LIFO uygula)
*/
function registerSession(User $user): void
{
$lifetime = (int) setting('auth_session_lifetime', 10080);
$existingToken = request()->cookie('mzb_login_token');
// 1. AYNI TARAYICI MI? (Cookie kontrolu)
if ($existingToken) {
$existing = DB::table('user_active_sessions')
->where('user_id', $user->id)
->where('login_token', $existingToken)
->first();
if ($existing) {
// AYNI TARAYICI - Mevcut kaydi guncelle
DB::table('user_active_sessions')
->where('id', $existing->id)
->update([
'session_id' => session()->getId(),
'last_activity' => now(),
'expires_at' => now()->addMinutes($lifetime),
]);
// Cookie'yi yenile (sure uzat)
cookie()->queue('mzb_login_token', $existingToken, $lifetime);
return; // YENI TOKEN OLUSTURMA!
}
}
// 2. FARKLI TARAYICI - Lock al (race condition)
$lock = Cache::lock("user_login:{$user->id}", 10);
if (!$lock->get()) {
throw new \Exception("Lutfen birkaç saniye bekleyin...");
}
try {
// 3. LIFO - Tum eski session'lari at (Limit=1)
DB::table('user_active_sessions')
->where('user_id', $user->id)
->get()
->each(function($session) {
// Atomic terminate: DB + Redis + Cache
$this->terminateSessionAtomic($session);
});
// 4. Yeni session olustur
$loginToken = bin2hex(random_bytes(32));
DB::table('user_active_sessions')->insert([
'user_id' => $user->id,
'login_token' => $loginToken,
'session_id' => session()->getId(),
'device_type' => $this->getDeviceType(),
'browser' => $agent->browser(),
'expires_at' => now()->addMinutes($lifetime),
'created_at' => now(),
]);
// 5. Cookie olustur
cookie()->queue('mzb_login_token', $loginToken, $lifetime);
} finally {
$lock->release();
}
}
┌─────────────────────────────────────────────────────────────┐
│ KULLANICI LOGIN │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────┐
│ mzb_login_token │
│ cookie var mi? │
└─────────────────────────┘
│ │
VAR YOK
│ │
▼ ▼
┌──────────────┐ ┌──────────────────┐
│ DB'de token │ │ FARKLI TARAYICI │
│ eslesiyor mu?│ │ (Yeni cihaz) │
└──────────────┘ └──────────────────┘
│ │ │
EVET HAYIR │
│ │ │
▼ └──────────────┤
┌─────────────────┐ │
│ AYNI TARAYICI │ │
│ Mevcut kaydi │ ▼
│ GUNCELLE │ ┌─────────────────┐
│ (yeni token YOK)│ │ 1. Lock al │
└─────────────────┘ │ 2. LIFO: eski │
│ │ session'lari │
│ │ ATOMIC sil │
│ │ 3. Yeni token │
│ │ olustur │
│ │ 4. Cookie yaz │
│ └─────────────────┘
│ │
└────────┬───────────┘
│
▼
┌──────────────────┐
│ DB'de 1 kayit │
│ (Limit=1 OK) │
└──────────────────┘
| Dosya | Satir | Aciklama |
|---|---|---|
| Modules/Muzibu/app/Services/DeviceService.php | 58-60 | 🔥 ANA SORUN: Cookie kontrolu yok |
| Modules/Muzibu/app/Services/DeviceService.php | 92-94 | LIFO yorum satirinda |
| app/Services/Auth/DeviceService.php | 1-99 | Eski sinif (SIL) |
| app/Http/Middleware/CheckDeviceLimit.php | 1-55 | Devre disi (return next) |
| app/Http/Controllers/Api/Auth/AuthController.php | 164-251 | checkSession API |
| Modules/Muzibu/.../SongStreamController.php | 75-84 | Stream kontrolu devre disi |