---
title: 'Kimlik Doğrulama Akışları'
source: 'https://academia.sh/tr/kurslar/php-web/kimlik-dogrulama-akislari'
course: 'Web ile PHP: Oturum, Veri ve Güvenlik'
language: tr
updated: '2026-10-21T05:03:37+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Oturum tabanlı ve imzalı taşıyıcı belirteçli akışı yan yana kurar ve isteğin kimliğini taraf ölçümüyle sınıflar'
    - 'hash_hmac() ve hash_equals() ile kullanici.imza biçiminde bir belirteç üretir ve doğrular'
    - 'Oturumun sunucuda iptal edilebildiğini, imzalı belirtecin ise anahtar değişmeden geçerli kaldığını ölçer'
    - 'Kursun on beş dersini taraf sınıfıyla tek tabloda okur'
---

# Kimlik Doğrulama Akışları

İsteğin kimliğini oturum tabanlı ve taşıyıcı belirteçli akışta ölçmek, imzanın neyi koruyup neyi korumadığını görmek ve kursun on beş dersini tek tabloda toplamak.

Parola Saklama dersi saklanan değeri ve onu üreten ayarı ölçtü. Parola doğrulandıktan sonra da bir soru kalır: sonraki istekler hangi kullanıcı adına işleniyor ve bunu kim belirliyor? **Kimlik doğrulama (authentication)** kullanıcının kim olduğunu saptar; ne yapabileceğini saptayan **yetkilendirme** ayrı bir iştir ve Kimlik Doğrulama ve Yetkilendirme dersinde çerçeve içinde ele alındı. Orada kapının isteği koşturup koşturmadığı ölçüldü. Burada her parça koşar; sorulan, isteğin kimliğini kimin değiştirebildiğidir.

**GÜ6.** Bu derste parola yalnız doğrulanır. Parola tahmin etmek, oturum çalmak, belirteç taklit etmek ve yetki aşmak modellenmez. İstemcinin sapması her zaman nötr bir değerdir: başka bir kullanıcının kendi girişinden aldığı oturum kimliği ya da belirteç.

## İki Akış

HTTP durumsuzdur; sunucu her isteği ayrı görür. Kimliği isteğe iki yoldan bağlarız. **Oturum tabanlı akışta** giriş sonrası sunucu rastgele bir oturum kimliği üretir, kimlikten kullanıcıya giden kaydı kendi belleğinde tutar ve kimliği istemciye verir; istemci onu her istekte geri gönderir. **Taşıyıcı belirteçli akışta** sunucu kayıt tutmaz: kullanıcı adını `hash_hmac()` ile imzalar ve `kullanici.imza` biçiminde bir **taşıyıcı belirteç (bearer token)** verir. İstemci belirteci her istekte, örneğin `Authorization` başlığında taşır; sunucu imzayı yeniden hesaplayıp `hash_equals()` ile karşılaştırır.

Ölçüm çekirdeği önceki derslerdekiyle aynıdır: `sina()` sonucu bir kez sapmasız, sonra her dış tarafın sapmasıyla hesaplar; `taraf()` sırayla istemciye, üçüncü tarafa, ortama bakar ve hiçbiri değiştiremediyse sunucuyu söyler. Dosya her derste olduğu gibi değişmeden verilir.

```php
<?php
// taraf.php — bu sonucu kim değiştirebiliyor?
declare(strict_types=1);

// Kodun dışındaki taraflar, karar sırasıyla: her istek, her dış çağrı, her dağıtım.
const DIS_TARAFLAR = ['istemci', 'üçüncü taraf', 'ortam'];

/** Sonucu bir kez sapmasız, sonra her dış tarafın sapmasıyla ayrı ayrı hesaplar. */
function sina(callable $sonuc, array $sapmalar): array {
    $taban = $sonuc([]);
    $degisti = [];
    foreach (DIS_TARAFLAR as $taraf) {
        if (array_key_exists($taraf, $sapmalar)) {
            $degisti[$taraf] = $sonuc([$taraf => $sapmalar[$taraf]]) !== $taban;
        }
    }
    return $degisti;
}

/** Sonucu değiştirebilen ilk dış taraf; hiçbiri değiştiremiyorsa sunucu. */
function taraf(array $degisti): string {
    foreach (DIS_TARAFLAR as $t) {
        if ($degisti[$t] ?? false) return $t;
    }
    return 'sunucu';
}

function tarafRaporu(string $ad, callable $sonuc, array $sapmalar): string {
    $degisti = sina($sonuc, $sapmalar);
    $satirlar = [];
    foreach ($degisti as $t => $d) $satirlar[] = $t . ($d ? ' değiştirdi' : ' değiştiremedi');
    $sonTaraf = taraf($degisti);
    echo "$ad → $sonTaraf\n    ", implode(' · ', $satirlar), "\n";
    return $sonTaraf;
}
```

Aşağıdaki dosya iki akışı kurar. Parolalar yalnız `password_verify()` ile sınanır, oturum kimliği `random_bytes()` ile üretilir ve belirteç imzası `hash_hmac('sha256', ...)` ile atılır. İmza anahtarı burada bir eğitim dizgesidir; gerçek bir uygulamada anahtar kodda durmaz, ortam değişkeninden okunur.

```php
<?php
// kimlik.php — oturum ve belirteç akışı
declare(strict_types=1);

const IMZA_ANAHTARI = 'ders-anahtari';

function karmalar(): array {
    $karmalar = [];
    foreach (['ayse' => 'parola-bir', 'mehmet' => 'parola-iki'] as $kullanici => $parola) {
        $karmalar[$kullanici] = password_hash($parola, PASSWORD_BCRYPT, ['cost' => 10]);
    }
    return $karmalar;
}

function girisDogrula(array $karmalar, string $kullanici, string $parola): bool {
    return isset($karmalar[$kullanici]) && password_verify($parola, $karmalar[$kullanici]);
}

final class OturumDeposu {
    private array $kayitlar = [];

    public function ac(string $kullanici): string {
        $kimlik = bin2hex(random_bytes(16));
        $this->kayitlar[$kimlik] = $kullanici;
        return $kimlik;
    }

    public function kullanici(string $kimlik): string {
        return $this->kayitlar[$kimlik] ?? 'anonim';
    }

    public function kapat(string $kimlik): void {
        unset($this->kayitlar[$kimlik]);
    }
}

function belirtecUret(string $kullanici, string $anahtar = IMZA_ANAHTARI): string {
    return $kullanici . '.' . hash_hmac('sha256', $kullanici, $anahtar);
}

function belirtecKullanici(string $belirtec, string $anahtar = IMZA_ANAHTARI): string {
    $parcalar = explode('.', $belirtec, 2);
    if (count($parcalar) !== 2) return 'anonim';
    $beklenen = hash_hmac('sha256', $parcalar[0], $anahtar);
    return hash_equals($beklenen, $parcalar[1]) ? $parcalar[0] : 'anonim';
}
```

## İsteğin Kimliği

Sonuç, isteğin işlendiği kullanıcı adıdır. İstemcinin sapması, başka bir kullanıcının kendi girişinden aldığı kimlik bilgisini sunmaktır: oturum akışında `mehmet`'in oturum kimliği, belirteç akışında `mehmet`'in belirteci. Rastgele değerler basılmaz; yalnız uzunlukları ve sonuçları basılır.

```php
<?php
// akis.php — isteğin kimliği, iki akış
declare(strict_types=1);
require 'taraf.php';
require 'kimlik.php';

$karmalar = karmalar();
foreach (['ayse' => 'parola-bir', 'mehmet' => 'parola-iki'] as $kullanici => $parola) {
    echo "giriş $kullanici ", var_export(girisDogrula($karmalar, $kullanici, $parola), true), "\n";
}
echo 'yanlış parola ', var_export(girisDogrula($karmalar, 'ayse', 'parola-iki'), true), "\n";

$depo = new OturumDeposu();
$oturumAyse = $depo->ac('ayse');
$oturumMehmet = $depo->ac('mehmet');
$belirtecAyse = belirtecUret('ayse');
$belirtecMehmet = belirtecUret('mehmet');
echo 'oturum kimliği ', strlen($oturumAyse), ' karakter · imza ', strlen(explode('.', $belirtecAyse)[1]), " karakter\n";

tarafRaporu('kimlik (oturum)', fn(array $s) => $depo->kullanici($s['istemci'] ?? $oturumAyse), ['istemci' => $oturumMehmet]);
tarafRaporu('kimlik (belirteç)', fn(array $s) => belirtecKullanici($s['istemci'] ?? $belirtecAyse), ['istemci' => $belirtecMehmet]);

echo 'uyuşmayan imza ', belirtecKullanici('ayse.' . str_repeat('0', 64)), "\n";
echo 'tanınmayan oturum kimliği ', $depo->kullanici(str_repeat('0', 32)), "\n";
```

```
giriş ayse true
giriş mehmet true
yanlış parola false
oturum kimliği 32 karakter · imza 64 karakter
kimlik (oturum) → istemci
    istemci değiştirdi
kimlik (belirteç) → istemci
    istemci değiştirdi
uyuşmayan imza anonim
tanınmayan oturum kimliği anonim
```

İki akışta da sonuç **istemcidir**. İstemci sunduğu oturum kimliğini ya da belirteci değiştirince isteğin kimliği `ayse`'den `mehmet`'e geçti. Çünkü kimliği isteğe taşıyan, her istekte onu gönderen istemcidir; sunucu yalnız sunulan bilgiyi doğrular. Doğrulama, aynı akışın iki ayrı noktasında farklı çalışır: oturum akışında sunucu kimliği kendi kaydında arar, belirteç akışında imzayı hesaplayıp karşılaştırır.

**GÜ7.** Son iki satır savunmanın sınırını gösterir. İmzası uyuşmayan belirteç bir kullanıcı adı üretmedi, tanınmayan oturum kimliği de üretmedi: ikisi de `anonim` verdi. İstemci bir kullanıcı adı seçemez; elinde sunucunun kendisine verdiği kimlik bilgilerinden birini sunabilir ya da hiçbirini sunamaz. Yani savunma sonucu istemciden almaz, istemcinin seçebileceği kümeyi sunucunun verdiği değerlere daraltır. Bu, kursun başından beri tekrarlanan cümledir: savunma her zaman sahibi değiştirmez, kimi zaman yalnız neyin değiştirilebileceğini daraltır.

Çerezler dersi imzalı çerezde aynı şeyi göstermişti. Oturumlar dersinde sepeti sunucuya taşıyan düzenek burada kimliği taşımaz, çünkü kimliğin kendisi istemcinin elindeki bir değerdir; Oturumlar dersinin sınırı da aynıydı: hangi oturumun açılacağı istemcide kalır.

## Sınırlayıcı Ölçüm

İki akışın sonucu aynı tarafa düştü, ama sunucunun elindeki çare aynı değil. Oturum akışında sunucu kaydı sildiğinde kimlik artık hiçbir kullanıcıya gitmez. Belirteç akışında sunucu kayıt tutmadığı için silecek bir şey yoktur; imza anahtarı değişmedikçe belirteç geçerli kalır. Anahtar ortamdan geliyorsa onu değiştiren dağıtımdır ve değişiklik bütün belirteçleri birden düşürür.

```php
<?php
// cikis.php — çıkış ve anahtar değişimi
declare(strict_types=1);
require 'taraf.php';
require 'kimlik.php';

$depo = new OturumDeposu();
$oturum = $depo->ac('ayse');
$belirtec = belirtecUret('ayse');

echo 'çıkıştan önce oturum ', $depo->kullanici($oturum), ' · belirteç ', belirtecKullanici($belirtec), "\n";
$depo->kapat($oturum);
echo 'çıkıştan sonra oturum ', $depo->kullanici($oturum), ' · belirteç ', belirtecKullanici($belirtec), "\n";

tarafRaporu(
    'kimlik (anahtar ortamdan)',
    fn(array $s) => belirtecKullanici($belirtec, $s['ortam'] ?? IMZA_ANAHTARI),
    ['ortam' => 'yeni-anahtar']
);
```

```
çıkıştan önce oturum ayse · belirteç ayse
çıkıştan sonra oturum anonim · belirteç ayse
kimlik (anahtar ortamdan) → ortam
    ortam değiştirdi
```

Çıkıştan sonra oturum `anonim` verdi, belirteç `ayse` vermeyi sürdürdü. Belirtecin çıkışta ortadan kalkmasını isteyen bir uygulama sunucuya ayrıca bir iptal kaydı eklemek zorundadır; bu da belirtecin kayıtsız olma avantajını geri alır. Anahtar değişince belirteç düştü ve sonucu değiştiren **ortamdır**: anahtarı dağıtım belirler. **GÜ8.** Bu derste süre ölçülmez; bir belirtecin bitiş zamanı taşıması ya da oturumun boşta kalınca kapanması saat gerektirir ve ölçüm kapsamında değildir. Burada yalnız sunucunun hangi çareye sahip olduğuna bakıldı.

## Özet

- Bu dersin ölçü sınıfı **istemci**: oturum kimliğini ya da belirteci değiştiren istemci isteğin kimliğini değiştirdi, iki akışta da.
- Oturum akışı kimliği sunucu belleğindeki bir kayıttan, belirteç akışı `hash_hmac()` imzasını `hash_equals()` ile doğrulayarak çözer; ikisi de tanınmayan değeri `anonim`'e düşürür.
- İmza istemcinin seçebileceği kümeyi sunucunun verdiği belirteçlerle sınırlar, sahibi değiştirmez.
- Oturum sunucuda iptal edilir; imzalı belirteç anahtar değişmedikçe geçerli kalır ve anahtar ortamdan geliyorsa onu değiştiren ortamdır.

## Kurs Kapanışı

Bu kursta on beş derste bir sonucu kimin değiştirebildiğini ölçtük: oturum ve durum, veri erişimi, güvenlik. Her ders kendi sonucunu ve bir karşıt ya da sınırlayıcı ölçümünü taşıdı. Aşağıdaki tablo hepsini tek yerde toplar; taraf hücreleri kaynak dersin özetinden alınmıştır.

| Ders | Ölçülen sonuç | Taraf | Sapma ya da karşıt ölçüm |
|---|---|---|---|
| Çerezler | Çerezdeki sepet, imzalı çerez | istemci | İmza değiştirilen değeri fark etti, sahibi değiştirmedi |
| Oturumlar | `$_SESSION`'daki sepet | sunucu | Aynı `sepet=5` çerezde sonucu değiştirdi |
| Yapılandırma ve Ortam Değişkenleri | `UYG_VERITABANI` ile bağlantı adı | ortam | Koda yazılan değer sunucuda kalır, taşınmaz |
| Veritabanı Erişim Katmanı | Dönen değerin tipi | ortam | Açık `int` dönüşümüyle sunucu |
| İşlemler | İki hesabın bakiye toplamı | sunucu | İşlemsiz aktarımda ortam toplamı değiştirdi |
| Göç Yönetimi | Uygulanan göç sayısı | ortam | Şema sürümü her ortamda aynı: sunucu |
| Nesne–Tablo Bağlamasının Sorguları | Gönderilen sorgu sayısı | sunucu | Tembel yüklemede satırla büyüdü: istemci |
| Veri Biçimleri | Ayrıştırılan fiyat | üçüncü taraf | Kendi JSON'umuzdaki sayı gösterimi: sunucu |
| HTTP İstemcisi | Servisin bildirdiği fiyat | üçüncü taraf | Varsayılan değer sonucu sınırlar, sahibi değiştirmez |
| Girdi Doğrulama ve Arındırma | Doğrulanan adet | istemci | Arındırma bozuk girdiyi başka değere çevirir |
| SQL Enjeksiyonu Önleme | `prepare()`'e giden metin | sunucu | Birleştirmede istemci |
| Siteler Arası Betik Çalıştırma Önleme | Basılan HTML | istemci | Çift kaçışlama metni bozar |
| İstek Sahteciliği Koruması | E-posta güncellemesi | sunucu | Belirteçsiz güncellemede üçüncü taraf |
| Parola Saklama | Karma öneki | ortam | Açık maliyette sunucu |
| Kimlik Doğrulama Akışları | İsteğin kimliği | istemci | Anahtar ortamdan gelince ortam |

Tabloda iki ayrı dağılım var ve ikisi ayrı şeyleri sayar. **Derslerin dağılımı** her dersin ölçü sınıfını sayar: 5 sunucu · 4 ortam · 4 istemci · 2 üçüncü taraf. **Çekirdeğin dağılımı** Çerezler dersinde koşturulan on sonucu sayar: 4 sunucu · 2 ortam · 2 istemci · 2 üçüncü taraf. Biri on beş dersin, öteki on ölçümün dağılımıdır; aynı sayılar değildir ve biri ötekini doğrulamaz.

Kursun söylediği tek cümle şudur: bir web uygulamasında sonucun sahibi kodu yazan değildir. İstemci isteği, ortam ayarı, üçüncü taraf veriyi getirir; savunma düzenekleri sahibi kimi zaman sunucuya taşır, kimi zaman yalnız daraltır. Sıradaki kurs bu uygulamayı üretim ortamına taşır: dağıtım, çalıştırma ve başarım konusu.
