---
title: 'Oturum Yönetimi Hataları'
source: 'https://academia.sh/tr/kurslar/guvenli-kodlama/oturum-yonetimi-hatalari'
course: 'Güvenli Kodlama'
language: tr
updated: '2026-08-17T18:06:42+00:00'
license: 'CC BY-SA 4.0'
---

# Oturum Yönetimi Hataları

Oturum kararlarının akış kümesi üzerinde sayılması: yedi akışın dördü oturumun yetki düzeyini yükseltir ve ikisi kimliği yenilemediği için sabitleme noktasıdır, üç geçersiz kılma akışının ikisi sunucu tarafında hiçbir kaydı silmediği için sekiz oturum yaşamaya devam eder, merkezî oturum kalıbı bu sayıyı ikiye indirir, sekizinci akış eklendiğinde dağıtık kurulumda dışarıda kalan akış beşe çıkar ve kalıbı hiç çağırmayan devir akışının yalnız yetki sürümüne bağlı bir kalıpla kapsandığı ölçülür.

Önceki ders kimliğin belirlendiği anı ölçtü ve sekiz noktanın beşinin kullanıcı varlığını
sızdırdığını saydı. Doğrulama başarılı olduğunda ise ortaya yeni bir nesne çıkar: sonraki
isteklerde kimliği yeniden sormamak için üretilen oturum kimliği. Bu kimlik bir kez üretilir
ve sonrasında pek çok akış tarafından değiştirilir, yükseltilir ya da bırakılır.

Oturumun ne olduğu ve nasıl saklandığı Kimlik ve Yetki kursunda kuruldu. Burada ölçülen şey
kararların **nerede verildiğidir**. Oturumla ilgili her karar bir akışın içinde alınır; akış
sayısı arttıkça karar sayısı artar ve her karar ayrı yazıldığında bazıları yanlış yazılır.
Bu dersin sorusu şudur: kaç akış oturum kimliğine dokunuyor, kaçı doğru dokunuyor, kaçı
dışarıda kalıyor.

## İki Kural, Yedi Akış

Oturum kimliğine dokunan akışlar iki türe ayrılır. **Yükseltme akışı** oturumun yetki
düzeyini artırır: anonim bir oturum girişli olur, girişli bir oturum ikinci etmeni
tamamlanmış olur, bir görevli oturumu yönetici yetkisi kazanır. Bu türde kural tektir —
düzey değiştiğinde oturum kimliği **yenilenir**. Yenilenmediğinde, düzey değişmeden önce
bilinen bir kimlik, düzey değiştikten sonra da geçerli kalır; buna **oturum sabitleme
(session fixation)** denir.

**Geçersiz kılma akışı** ise yetkiyi geri alır: çıkış, parola değişikliği, aboneliğin başka
bir kişiye devri. Bu türde kural sunucu tarafındadır — silinecek şey defterdeki kayıttır.
İstemci tarafında çerezin silinmesi defterle ilgili hiçbir şey yapmaz; kimliği elinde tutan
bir istemci onu göndermeye devam edebilir.

Aşağıdaki akış kümesi ve oturum defteri bir **modeldir**: gerçek bir oturum deposu, gerçek
bir çerez ve gerçek bir abone yoktur.

```js
// oturum/model.mjs — abone portalinin oturum akislari ve sunucu tarafi oturum defteri (model):
// gercek bir oturum deposu, gercek bir cerez ve gercek bir abone yok.

// KH5: bir akis oturumun yetki duzeyini yukseltiyorsa oturum kimligi yenilenmelidir
// (beklenen: "yenile"); yetkiyi geri aliyorsa etkilenen oturumlar sunucu tarafinda silinmelidir
// (beklenen: cikis icin "tek", digerleri icin "hepsi"). `simdi` alani bugunku davranistir.
export const AKIS = [
  { ad: "portal-giris",            tur: "yukselt",  simdi: "yenile" },
  { ad: "ikinci-etmen-onayi",      tur: "yukselt",  simdi: "yerinde" },
  { ad: "rol-yukseltme",           tur: "yukselt",  simdi: "yerinde" },
  { ad: "saha-uygulamasi-eslesme", tur: "yukselt",  simdi: "yenile" },
  { ad: "cikis",                   tur: "gecersiz", simdi: "tek" },
  { ad: "parola-degistirme",       tur: "gecersiz", simdi: "hicbiri" },
  { ad: "abone-devri",             tur: "gecersiz", simdi: "hicbiri" },
];
export const beklenen = (a) =>
  a.tur === "yukselt" ? "yenile" : a.ad === "cikis" ? "tek" : "hepsi";

// KH6: oturum defteri sunucu tarafindadir; bir kimlik ancak defterde kaydi varken cozulur.
// Istemci tarafinda cerezin silinmesi deftere dokunmaz. `surumlu` acikken kayit abonenin
// yetki surumunu tasir ve surum degistiginde silinmeden gecersizlesir.
export function defterAc({ surumlu = false } = {}) {
  const kayit = new Map(), surum = new Map();
  let sayac = 0;
  const s = (abone) => surum.get(abone) ?? 1;
  return {
    ac(abone, duzey) {
      const k = `o-${++sayac}`;
      kayit.set(k, { abone, duzey, surum: s(abone) });
      return k;
    },
    coz(k) {
      const v = kayit.get(k);
      if (!v) return null;
      return surumlu && v.surum !== s(v.abone) ? null : v;
    },
    yerinde(k, duzey) { const v = kayit.get(k); if (v) v.duzey = duzey; },
    sil: (k) => kayit.delete(k),
    silHepsi(abone) {
      let n = 0;
      for (const [k, v] of kayit) if (v.abone === abone) { kayit.delete(k); n++; }
      return n;
    },
    surumArtir(abone) { surum.set(abone, s(abone) + 1); },
    canli(abone) {
      return [...kayit.keys()].filter((k) => this.coz(k)?.abone === abone).length;
    },
  };
}
```

```js
// oturum/olcum.mjs — kac akis oturum kimligi uretiyor, kaci yenilemiyor, gecersiz kilma
// yoksa kac oturum yasamaya devam ediyor.
import { AKIS, beklenen, defterAc } from "./model.mjs";
const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));

// KH7: sabitleme noktasi, yukseltme akisindan sonra eski kimligin hala yukseltilmis duzeyi
// cozdugu akistir. Asagidaki dongu bunu defter uzerinde gercekten kosturur.
const yukseltme = AKIS.filter((a) => a.tur === "yukselt");
const A = [-24, 10, 22, 20];
console.log(`1. ${yukseltme.length} yukseltme akisi: eski kimlik giristen sonra ne cozuyor`);
yaz(A, "akis", "simdi", "eski kimligin duzeyi", "sabitleme noktasi");
let sabitleme = 0;
for (const a of yukseltme) {
  const d = defterAc();
  const eski = d.ac("a-4471", "anonim");
  if (a.simdi === "yenile") { d.sil(eski); d.ac("a-4471", "girisli"); }
  else d.yerinde(eski, "girisli");
  const duzey = d.coz(eski)?.duzey ?? "cozulmuyor";
  if (duzey === "girisli") sabitleme++;
  yaz(A, a.ad, a.simdi, duzey, duzey === "girisli" ? "EVET" : "hayir");
}
console.log(`oturum kimligi ureten akis: ${yukseltme.length}, yenilemeyen: ${sabitleme}`);

// KH8: her abonenin uc ayri uctan acilmis uc canli oturumu vardir; olculen sey bir gecersiz
// kilma akisindan sonra defterde kalan oturum sayisidir.
const uygula = (siyaset, d, k) =>
  siyaset === "tek" ? d.sil(k) : siyaset === "hepsi" ? d.silHepsi("a-4471") : 0;
const yasayan = (siyaset) => {
  const d = defterAc();
  const kimlikler = [d.ac("a-4471", "girisli"), d.ac("a-4471", "girisli"), d.ac("a-4471", "girisli")];
  uygula(siyaset, d, kimlikler[0]);
  return d.canli("a-4471");
};
const gecersiz = AKIS.filter((a) => a.tur === "gecersiz");
const B = [-22, 12, 10, 12, 10];
console.log("\n2. gecersiz kilma akislari (baslangic: her akista 3 canli oturum)");
yaz(B, "akis", "simdi", "yasayan", "beklenen", "yasayan");
let simdiToplam = 0, kalipToplam = 0;
for (const a of gecersiz) {
  const s = yasayan(a.simdi), b = yasayan(beklenen(a));
  simdiToplam += s; kalipToplam += b;
  yaz(B, a.ad, a.simdi, s, beklenen(a), b);
}
yaz(B, "toplam", "", simdiToplam, "", kalipToplam);

// 3. kapsama: kac akis kalibin bekledigi davranisi zaten yapiyor
const kapsanan = (kume) => kume.filter((a) => a.simdi === beklenen(a)).length;
const YENI = { ad: "saha-cihaz-degisimi", tur: "yukselt", simdi: "yerinde" };
const genis = [...AKIS, YENI];
const C = [-34, 6, 10, 10, 12];
console.log("\n3. akis kumesi kapsamasi");
yaz(C, "kume", "akis", "kapsanan", "disarida", "disarida %");
for (const [ad, k, merkezi] of [
  ["bugunku dagitik durum", AKIS, false],
  ["merkezi oturum kalibi", AKIS, true],
  ["yeni akis eklendi, dagitik", genis, false],
  ["yeni akis eklendi, merkezi kalip", genis, true],
]) {
  const kap = merkezi ? k.length : kapsanan(k);
  yaz(C, ad, k.length, kap, k.length - kap, (((k.length - kap) / k.length) * 100).toFixed(1));
}

// 4. kalibin ulasamadigi akis: `abone-devri` abonelik kaydini portalin disindan degistirir ve
// oturum kalibini cagirmayabilir. Surume bagli kalipta cagri gerekmez.
const devir = (surumlu, bildirir) => {
  const d = defterAc({ surumlu });
  d.ac("a-4471", "girisli"); d.ac("a-4471", "girisli"); d.ac("a-4471", "girisli");
  if (bildirir) d.silHepsi("a-4471");
  d.surumArtir("a-4471");                       // abonelik kaydi her durumda degisir
  return d.canli("a-4471");
};
const D = [-24, 16, 16, 16];
console.log("\n4. abone-devri akisi (3 canli oturum): kalip cagrilmazsa ne oluyor");
yaz(D, "kurulum", "olay bildirdi", "yasayan oturum", "kapsanan akis");
for (const [ad, surumlu, bildirir] of [
  ["cagriya bagli kalip", false, true],
  ["cagriya bagli kalip", false, false],
  ["surume bagli kalip", true, false],
]) yaz(D, ad, bildirir ? "evet" : "hayir", devir(surumlu, bildirir),
  `${surumlu || bildirir ? gecersiz.length : gecersiz.length - 1} / ${gecersiz.length}`);
```

```
1. 4 yukseltme akisi: eski kimlik giristen sonra ne cozuyor
akis                         simdi  eski kimligin duzeyi   sabitleme noktasi
portal-giris                yenile            cozulmuyor               hayir
ikinci-etmen-onayi         yerinde               girisli                EVET
rol-yukseltme              yerinde               girisli                EVET
saha-uygulamasi-eslesme     yenile            cozulmuyor               hayir
oturum kimligi ureten akis: 4, yenilemeyen: 2

2. gecersiz kilma akislari (baslangic: her akista 3 canli oturum)
akis                         simdi   yasayan    beklenen   yasayan
cikis                          tek         2         tek         2
parola-degistirme          hicbiri         3       hepsi         0
abone-devri                hicbiri         3       hepsi         0
toplam                                     8                     2

3. akis kumesi kapsamasi
kume                                akis  kapsanan  disarida  disarida %
bugunku dagitik durum                  7         3         4        57.1
merkezi oturum kalibi                  7         7         0         0.0
yeni akis eklendi, dagitik             8         3         5        62.5
yeni akis eklendi, merkezi kalip       8         8         0         0.0

4. abone-devri akisi (3 canli oturum): kalip cagrilmazsa ne oluyor
kurulum                    olay bildirdi  yasayan oturum   kapsanan akis
cagriya bagli kalip                 evet               0           3 / 3
cagriya bagli kalip                hayir               3           2 / 3
surume bagli kalip                 hayir               0           3 / 3
```

Sayılar **ölçüm** sınıfındadır; girdileri KH5–KH8'dir.

## Dört Akış Üretiyor, İkisi Yenilemiyor

Birinci tablo yükseltme tarafını sayar. Dört akış oturumun yetki düzeyini değiştiriyor;
ikisi kimliği yeniliyor, ikisi kaydı **yerinde** yükseltiyor. Yerinde yükselten iki akışta
eski kimlik `girisli` düzeyini çözmeye devam ediyor; yenileyen iki akışta `cozulmuyor`.

İki sabitleme noktasının hangileri olduğu öğreticidir. `portal-giris` doğru yazılmıştır —
bu akış herkesin baktığı akıştır ve kural en çok orada bilinir. Yanlış yazılan ikisi
`ikinci-etmen-onayi` ve `rol-yukseltme`'dir: ikisi de girişten **sonra** gelen ve girişin
kendisi sanılmayan akışlardır. Kural "girişte kimlik yenilenir" biçiminde ezberlendiğinde,
düzeyi girişten sonra artıran akışlar kuralın dışında kalır.

Sayının anlamı da buradadır. "Oturum sabitlemeye karşı korunuyoruz" cümlesi tek bir akış
hakkında doğru, dört akış hakkında yarı doğrudur. Ölçülebilir biçimi şudur: **oturum
kimliği üreten akış 4, yenilemeyen 2.**

Yerinde yükseltmenin niçin yazıldığını görmek de kolaydır. Kaydı yerinde güncellemek daha
az iş yapar: yeni bir kimlik üretilmez, istemciye yeni bir değer gönderilmez, aradaki
istekler etkilenmez. Yenileme ise kaydın kopyalanmasını, eskisinin silinmesini ve istemcinin
yeni değeri almasını gerektirir. Sabitleme noktalarının ikisinin de bu ucuz yolu seçmiş
olması bir dikkatsizlik değil, kuralın o akışta hiç sorulmamış olmasıdır.

## Sekiz Oturum Yaşamaya Devam Ediyor

İkinci tablo geçersiz kılma tarafını sayar. Her akış üç canlı oturumu olan bir abone
üzerinde koşuyor; ölçülen şey akıştan sonra defterde kalan kayıt sayısıdır.

`cikis` akışı kendi oturumunu siliyor ve geriye iki oturum kalıyor. Bu doğrudur: bir uçtan
çıkmak öteki uçlardaki oturumları kapatmaz. `parola-degistirme` ve `abone-devri` ise
defterde hiçbir kaydı silmiyor; üçü de yaşamaya devam ediyor. Toplam sekiz oturum, yetkinin
geri alındığı varsayılan üç akıştan sonra hâlâ canlı.

İki akışın niçin bu durumda olduğu, işin nerede yapıldığıyla ilgilidir. Parola değiştirme
akışının görünür işi kimlik bilgisini güncellemektir; oturum defterine dokunmak o işin
parçası gibi görünmez. Abone devri ise portalın değil, aboneliği yöneten tarafın akışıdır ve
oturum defterinin varlığından haberdar olmayabilir. Her iki durumda da eksik olan şey bir
denetim değil, **bir çağrıdır**.

Sayının nasıl ölçüldüğü de önemlidir. Her akış üç canlı oturumu olan bir abone üzerinde
koşuyor; üç oturum aynı kişinin ayrı uçlarıdır. Abone başına oturum sayısı arttıkça, geçersiz
kılmayan bir akışın bıraktığı oturum sayısı doğrudan artar. Bu yüzden ölçünün birimi "akış"
değil, **akıştan sonra yaşayan oturum**tur: iki eksik akış, oturum sayısıyla çarpılarak
büyüyen bir kalemdir.

Beklenen sütun aynı akışları doğru siyasetle koşuyor: `cikis` için `tek`, diğer ikisi için
`hepsi`. Toplam sekizden **ikiye** iniyor ve kalan iki oturum çıkış akışının öteki
uçlarındaki oturumlardır — kapatılmaması gereken oturumlar. Ölçüm burada bir şeyi daha
gösteriyor: doğru sayı sıfır değildir. "Hepsini kapat" her akış için doğru olsaydı,
kullanıcı bir uçtan çıktığında öteki uçlardan da düşerdi.

## Kalıbın Kapsadığı Akış

Üçüncü tablo kapsamayı sayar. Yedi akışın **üçü** kalıbın beklediği davranışı yapıyor;
dördü dışarıda — dışarıda kalan oran %57,1.

Merkezî oturum kalıbı tek bir işlevdir ve iki şeyi bir yerde tutar: hangi olayın hangi
siyasete karşılık geldiği ve o siyasetin defter üzerinde nasıl uygulandığı. Akışlar kararı
kendileri vermez, olayı bildirir. Bu kurulumda kapsanan akış sayısı 7'dir ve dışarıda kalan
sıfırdır — ama bu sıfır, kalıbın akıllı olmasından değil, kararın **bir kez** verilmiş
olmasından gelir.

Son iki satır yeni akış sorusunu yanıtlar. Sekizinci akış — `saha-cihaz-degisimi`, bir saha
görevlisinin uçbirimini değiştirmesi — dağıtık kurulumda dışarıda kalanı 4'ten 5'e çıkarır
ve oran %62,5'e yükselir. Merkezî kalıpta aynı akış bir olay bildirir ve dışarıda kalan
sıfır kalır. Dağıtık kurulumda her yeni akış, iki kuralın ikisini de yeniden hatırlamayı
gerektirir; kalıpta yalnız olayın adını doğru yazmayı.

## Kalıbı Çağırmayan Akış

Dördüncü tablo, üçüncü tablodaki sıfırın hangi varsayıma dayandığını açar. Merkezî kalıp bir
**çağrı** kalıbıdır: akış olayı bildirdiğinde çalışır, bildirmediğinde çalışmaz. Bu varsayım
yedi akışın altısı için sorunsuzdur, çünkü altısı portalın kendi kodudur.

`abone-devri` farklıdır. Abonelik kaydını değiştiren taraf portal değildir; devir, abonelik
kaydını doğrudan güncelleyen ayrı bir akıştır. Tablo iki durumu ayırıyor: akış olayı
bildirdiğinde üç oturum sıfıra iniyor, bildirmediğinde **üçü de yaşamaya devam ediyor** ve
kapsanan akış 3'ten 2'ye düşüyor. Merkezî kalıp yerinde duruyor, doğru yazılmış ve
çalışıyor; kapsamadığı tek şey onu çağırmayan akış.

Son satır kalıbın biçimini değiştiriyor. Oturum kaydı abonenin **yetki sürümünü** taşırsa,
çözümleme her istekte kayıttaki sürümü abonenin güncel sürümüyle karşılaştırır. Devir akışı
abonelik kaydını değiştirdiğinde sürüm zaten artar; oturum kalıbını hiç çağırmamasına karşın
üç oturum da geçersizleşir — yaşayan oturum 0, kapsanan akış 3/3. Fark, savunmanın nereye
bağlandığıdır: çağrıya bağlı kalıp akışın hatırlamasını bekler, veriye bağlı kalıp akışın
zaten yaptığı değişikliği ölçüt olarak kullanır. İkincisinin kapsaması, akış kümesi
büyüdükçe sabit kalır.

## Özet

- Oturum kararları iki kurala indirgenir: yetki düzeyi yükselten akış kimliği yeniler, yetki
  geri alan akış sunucu tarafındaki kaydı siler. İkisi de akış başına ayrı verilir.
- Yedi akışın dördü oturum kimliği üretiyor; ikisi kimliği yenilemediği için sabitleme
  noktasıdır ve yanlış yazılan ikisi girişten sonra gelen akışlardır.
- Üç geçersiz kılma akışının ikisi defterde hiçbir kaydı silmiyor; üçünden sonra sekiz oturum
  yaşamaya devam ediyor, doğru siyasetle bu sayı ikiye iniyor.
- Doğru sayı sıfır değildir: çıkış akışından sonra öteki uçlardaki iki oturumun yaşaması
  beklenen sonuçtur; siyaset akış başına ayrılır.
- Yedi akışın üçü kalıbın beklediğini yapıyor, dördü dışarıda kalıyor (%57,1); merkezî kalıpta
  sekizinci akış eklendiğinde dışarıda kalan sıfır kalırken dağıtık kurulumda beşe çıkıyor.
- Çağrıya bağlı kalıp, kendisini çağırmayan akışı kapsamaz: devir akışı olayı bildirmediğinde
  üç oturum da yaşıyor. Oturum kaydı abonenin yetki sürümünü taşıdığında aynı akış hiçbir
  çağrı yapmadan üç oturumu geçersiz kılıyor.

## Sonraki Adım

Bu iki ders isteğin arkasındaki kimliği güvence altına aldı: kim olduğu sızdırılmadan
belirlendi ve o kimliğin taşıyıcısı doğru anlarda yenilendi, doğru anlarda silindi. Kimliğin
doğru bilinmesi ise kararın yalnız yarısıdır. Bilinen bir kimlik bir uca istek yolladığında
sorulması gereken ikinci soru vardır ve bu soru uç başına sorulur: bu kimlik **bu nesneye**
dokunabilir mi? Sonraki ders yetki matrisini çıkarır ve konunun en önemli sayısını verir:
kaç uç yalnız rol denetimi yapıyor, kaçı istenen nesnenin sahibini de denetliyor, yeni bir uç
eklendiğinde merkezî kalıp onu kapsıyor mu.
