Menu

PHP Session ve Cookie: session_start ve setcookie

Her sayfanın başında session_start() çağırın, sonra değerleri $_SESSION['key'] içinde saklayın; PHP onları sunucuda tutar ve ziyaretçiyi bir çerez üzerinden hatırlar. setcookie('name', 'value', $options) tarayıcıda küçük bir değer saklar ve $_COOKIE üzerinden geri okunur. Giriş, çıkış, flash mesajları, çerez seçeneklerini ve güvenlik ayarlarını öğrenin.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

Bir sayfanın başında session_start() çağırın, sonra $_SESSION['key'] değerini herhangi bir dizi gibi okuyup yazın: PHP onu sunucuda kaydeder ve ziyaretçinin bir sonraki isteğinde yeniden bulur. Tarayıcının tutması gereken küçük bir değer için setcookie('name', 'value', time() + 86400) çağırın ve sonraki isteklerde onu $_COOKIE['name'] üzerinden geri okuyun.

<?php
session_start();                        // before any output
setcookie('theme', 'dark', time() + 60 * 60 * 24 * 30);   // 30 days, also before output

$_SESSION['visits'] = ($_SESSION['visits'] ?? 0) + 1;
$theme = $_COOKIE['theme'] ?? 'light';  // set on an earlier visit
echo "You have opened this page {$_SESSION['visits']} times.";

Oturumlar ve çerezler yalnızca bir tarayıcıdan gelen birkaç HTTP isteği boyunca anlam taşır, bu yüzden buna ihtiyaç duyan örnekler düz koddur. Etraflarındaki mantık diziler üzerinde sıradan PHP'dir ve o kısım burada çalışır: çalıştırılabilir her blokta $session $_SESSION yerine geçer ve her çağrı bir istektir.

Bir PHP oturumu nasıl çalışır

  1. İlk session_start() rastgele bir id oluşturur, onu tarayıcıya PHPSESSID adlı bir çerezle gönderir ve size boş bir $_SESSION verir.
  2. İsteğin sonunda PHP $_SESSION dizisini sunucuda kaydeder (varsayılan olarak dosyalarda ya da Redis'te veya bir veritabanında).
  3. Bir sonraki istekte tarayıcı çerezi geri gönderir, session_start() id'yi okur ve kaydedilen diziyi yükler.

Tarayıcı veriyi asla görmez, yalnızca id'yi görür. Giriş yapmış kullanıcının id'sinin kendi çerezinizde değil $_SESSION içinde olmasının nedeni budur: bir ziyaretçi çerezlerini herhangi bir değere düzenleyebilir, ama $_SESSION dizisini düzenleyemez.

Bir oturumla kullanıcı girişi ve çıkışı

Giriş yapmak şudur: parolayı kontrol et, oturum id'sini yeniden oluştur, kullanıcı id'sini sakla. Çıkış yapmak bunun tersidir ve üç adımı vardır.

<?php
// login.php
session_start();

$user = find_user_by_email($_POST['email'] ?? '');
if ($user && password_verify($_POST['password'] ?? '', $user['password_hash'])) {
    session_regenerate_id(true);        // new id after login: stops session fixation
    $_SESSION['user_id'] = $user['id'];
    header('Location: /dashboard.php');
    exit;
}
$error = 'Wrong email or password.';
<?php
// any protected page
session_start();
if (!isset($_SESSION['user_id'])) {
    header('Location: /login.php');
    exit;
}
<?php
// logout.php
session_start();
$_SESSION = [];                                     // 1. forget the data

$p = session_get_cookie_params();                   // 2. delete the cookie
setcookie(session_name(), '', time() - 3600, $p['path'], $p['domain'], $p['secure'], $p['httponly']);

session_destroy();                                  // 3. delete the stored session
header('Location: /');
exit;

session_regenerate_id(true) göründüğünden daha önemlidir. Bir saldırgan bir kurbanın saldırganın bildiği bir oturum id'sini kullanmasını sağlayabilirse (örneğin bir bağlantı üzerinden) ve id girişten sonra aynı kalırsa, saldırgan da giriş yapmış olur. Girişte yeni bir id bu açığı kapatır. Parola kontrolünün kendisi password_hash sayfasında anlatılıyor.

Hareketsizlikten sonra bir oturumu sona erdirme

PHP'nin kendi temizliği (session.gc_maxlifetime, varsayılan 1440 saniye) rastgele çalışır ve güvenilir bir zaman aşımı değildir. Son isteğin zamanını saklayın ve kendiniz kontrol edin. Blok her durumu görebilmeniz için sabit zaman damgaları kullanır; $timeout değerini veya zamanları değiştirin.

09:05 ile 09:16:40 arasındaki boşluk 700 saniyedir, 15 dakikalık sınırın altındadır, bu yüzden kullanıcı içeride kalır. Bir sonraki boşluk 1000 saniyedir, bu yüzden oturum temizlenir.

Flash mesajları

Bir flash mesajı bir istekte ayarlanır ve bir sonrakinde bir kez gösterilir, tipik olarak bir yönlendirmeden sonra "Saved." mesajı. Onu oturumda saklayın, sonra tek adımda okuyup silin:

setcookie ile bir çerez ayarlama

setcookie() adı, değeri ve bir seçenekler dizisini alır (PHP 7.3 ve sonrası). Bir nedeniniz olmadıkça bu dört seçeneği her çerezde ayarlayın:

<?php
setcookie('theme', 'dark', [
    'expires'  => time() + 60 * 60 * 24 * 30,   // 30 days; 0 means "until the browser closes"
    'path'     => '/',                          // send it on every page, not just this folder
    'secure'   => true,                         // only over HTTPS
    'httponly' => true,                         // JavaScript cannot read it
    'samesite' => 'Lax',                        // not sent on most cross-site requests
]);

$theme = $_COOKIE['theme'] ?? 'light';

İki şey insanları şaşırtır:

  • $_COOKIE aynı istekte değişmez. Tarayıcının bu istekle gönderdiğini tutar. Şimdi ayarladığınız bir çerez $_COOKIE içinde bir sonraki istekte görünür.
  • Çerezler başlıktır, bu yüzden setcookie() tıpkı session_start() ve header() gibi herhangi bir çıktıdan önce çalışmalıdır.

Bir çerezi silmek için onu aynı ad ve path ile ve geçmişte bir son kullanma tarihiyle yeniden ayarlayın: setcookie('theme', '', ['expires' => time() - 3600, 'path' => '/']).

Bir çerezde dizi saklama

Bir çerez değeri en fazla yaklaşık 4 KB'lık bir dizgedir, bu yüzden yapılandırılmış veriyi JSON olarak saklayın ve geri geleni güvenilmez sayın: ziyaretçi onu değiştirebilir. Bir çerezi asla unserialize() ile açmayın: kendi sınıflarınızdan nesneler oluşturup sihirli metotlarını çalıştırabilir, json_decode() ise yalnızca diziler, dizgeler, sayılar, boolean değerler, null veya stdClass döndürür.

json_encode sayfası bayrakları anlatır. Birkaç kısa değerden büyük her şey için veriyi oturumda (veya bir veritabanında) tutun ve çerezde yalnızca bir anahtar saklayın.

"Beni hatırla" belirteçleri

Bir "beni hatırla" çerezi kullanıcı id'sini veya parola hash'ini tutmamalıdır. Çerezde uzun rastgele bir belirteç, veritabanında yalnızca onun hash'ini saklayın ve hash_equals() ile karşılaştırın:

Değerler her çalıştırmada değişir, çünkü random_bytes() rastgeledir. Veritabanı sızarsa hash'ler çerezler olmadan işe yaramaz ve hash_equals() sabit sürede karşılaştırır, böylece kontrol zamanlama bilgisi sızdırmaz.

Oturum ile çerez: hangisini kullanmalı

Oturum ($_SESSION)Çerez ($_COOKIE)
Saklandığı yerSunucudaTarayıcıda
Ziyaretçi okuyabilir veya düzenleyebilirHayır (yalnızca id)Evet
BoyutDepolamanızla sınırlıÇerez başına yaklaşık 4 KB
SüreTarayıcı kapanana veya oturum sona erene kadarexpires zamanına kadar
Kullanım alanıGiriş yapmış kullanıcı, sepet, CSRF belirteci, flash mesajlarıTema, dil, onay seçimi, "beni hatırla" belirteci

Sık yapılan hata: headers already sent

session_start(), setcookie() ve header() hepsi HTTP başlıkları gönderir ve başlıklar yalnızca gövdeden önce gönderilebilir. Önce gelen herhangi bir çıktı, dahil edilen bir dosyada <?php öncesindeki boş bir satır bile, şunu üretir:

Warning: session_start(): Session cannot be started after headers have already been sent in /var/www/page.php on line 3
Warning: Cannot modify header information - headers already sent by (output started at /var/www/page.php:2) in /var/www/page.php on line 4

İkinci mesaj çıktının nerede başladığını söyler (page.php:2): o satıra gidin ve çıktıyı kaldırın ya da session_start() çağrısını onun üstüne taşıyın. Yalnızca PHP içeren dosyalarda kapanış ?> etiketini yazmamak, ondan sonraki fazladan boşlukların çıktıya dönüşmesini önler.

Sıkça Sorulan Sorular

PHP'de oturum (session) ile çerez (cookie) arasındaki fark nedir?

Bir çerez ziyaretçinin tarayıcısında saklanır ve her istekle gönderilir, bu yüzden ziyaretçi onu okuyabilir ve değiştirebilir. Bir oturum verisini sunucuda saklar; tarayıcı bir çerezde (PHPSESSID) yalnızca rastgele bir oturum id'si tutar. Giriş yapmış kullanıcının id'si gibi güvenilmesi gereken her şeyi $_SESSION içine koyun.

PHP'de çıkışta bir oturumu nasıl yok ederim?

Veriyi boşaltın, oturum çerezini silin ve saklanan oturumu yok edin: $_SESSION = [];, sonra setcookie(session_name(), '', time() - 3600, '/'), sonra session_destroy();. Ardından bir sonraki sayfa temiz başlasın diye yönlendirin.

PHP'de bir çerezi nasıl silerim?

Onu aynı ad, yol ve alan adıyla ve geçmişte bir son kullanma tarihiyle yeniden ayarlayın: setcookie('theme', '', ['expires' => time() - 3600, 'path' => '/']);. Geçerli betiğin geri kalanı onu okuyorsa unset($_COOKIE['theme']) de yapın, çünkü $_COOKIE ancak bir sonraki istekte değişir.

Bir PHP oturumu ne kadar sürer?

Varsayılan olarak oturum çerezi tarayıcı kapanana kadar sürer (session.cookie_lifetime = 0) ve sunucu oturum verisini 1440 saniye (24 dakika) etkinlik olmadığında silebilir (session.gc_maxlifetime). Sabit bir zaman aşımı için son isteğin zamanını oturumda saklayın ve kendiniz kontrol edin.

session_start() neden headers already sent diyor?

Oturum id'si bir çerez başlığında taşınır ve başlıklar herhangi bir çıktıdan önce gönderilmelidir. Bir echo, HTML ya da <?php öncesindeki boş bir satır veya BOM bile çıktıyı önce gönderir. session_start() fonksiyonunu herhangi bir şey yazdırılmadan önce, betiğin en başında çağırın.

Coddy programlama dilleri çizimi

Coddy ile kodlamayı öğren

BAŞLA