İçeriğe geç
academia.sh

Ders 04 / 16

Çerezler ve Durum Taşıma

Çerezin kapsam kuralı hangi iletilere iliştiğini belirler, im kuralı saklanan yanıtın kime gideceğini; kırk alışverişte üç kapsam kuralı sırasıyla 11, 24 ve 40 ileti taşır ve imsiz kalan iki alışveriş aracıya iki yanlış paylaşılabilirlik kararı aldırır.

İçindekiler

Önceki ders içerik pazarlığını kurdu: aynı adres birden çok gösterime karşılık gelir ve aracı hangi kopyayı kime vereceğini başlık alanlarından çıkarır. Pazarlık, gösterimi isteğin biçim tercihine göre seçer — dil, kodlama, ortam türü. Bunların hepsi isteğin kendisinde yazılıdır ve aracı hepsini okur.

Peki yanıt biçime değil kişiye özelse? O zaman seçimi yapan alan artık tercihi değil, kimliği taşımak zorundadır. Çerez (cookie), kişiye özelliğin kendisini taşıyan alandır. Bu dersin sorusu çerezin ne işe yaradığı değil — aracının onu görünce ne bildiği, ve görmediğinde ne bilemediğidir.

Durumsuz Protokolde Durum

HTTP durumsuz (stateless) tanımlanır: her istek kendi başına anlaşılır olmalı, sunucu önceki isteği hatırlamak zorunda kalmamalıdır. Çerez bu tanımı bozmaz, etrafından dolaşır. Sunucu durumu kendinde tutmaz; istemcide tutar ve istemci onu her istekte geri gönderir. Böylece her istek yine kendi başına anlaşılır kalır, çünkü durum artık iletinin içindedir.

Alışveriş iki alandan ibarettir. Sunucu yanıtta Set-Cookie alanıyla bir ad–değer çifti ve ona bağlı nitelikleri bildirir; istemci sonraki isteklerde Cookie alanıyla ad–değer çiftini geri gönderir. Nitelikler yanıtta gider, geri dönüşte gitmez: istemci yalnız çifti yollar.

# ogretilen dokum , calistirilmamistir

sunucu -> istemci
  HTTP/1.1 200 OK
  Set-Cookie: oturum=k7; Path=/oturum; Domain=istasyon.ornek; Max-Age=3600;
              HttpOnly; SameSite=Strict; Secure
  Cache-Control: private
  Vary: Cookie

istemci -> sunucu
  GET /oturum/ozet HTTP/1.1
  Host: istasyon.ornek
  Cookie: oturum=k7

Niteliklerin her biri bir soruya yanıt verir. Domain ve Path çerezin kapsamını belirler: hangi konak ve hangi yol öneki için gönderileceğini. Max-Age ömrünü belirler; verilmezse çerez oturumluktur ve istemci kapandığında düşer. HttpOnly, çerezi belge içindeki betiklerin okumasına kapatır. SameSite, çerezin başka bir kaynaktan tetiklenen isteklerde taşınıp taşınmayacağını belirler. Secure, çerezi taşımanın türüne bağlar.

Yanıt tarafındaki iki alan aracıyı doğrudan ilgilendirir. Cache-Control: private, yanıtın paylaşılan bir önbelleğe konmaması gerektiğini bildirir. Vary: Cookie, saklanan kopyanın hangi istek alanına bağlı olduğunu bildirir — aynı adresin Cookie alanına göre ayrı kopyaları vardır. Ortak tanımın kişiye özel imi bu iki alanın taşıdığı bildirimdir.

Kimlik doğrulama akışının kendisi bu kursun konusu değildir; oturum açma, oturum yenileme ve belirteç kullanımı Kimlik Doğrulama ve Yetkilendirme kursunda kuruldu. Burada çerez bir kimlik düzeneği olarak değil, bir kapsam kuralı olarak ölçülür.

Çerezin Değeri Aracıya Ne Söyler

Çerez bir ad–değer çiftidir ve değerin anlamını yalnız sunucu bilir. oturum=k7 dizgisi aracı için bir dizgidir: kimin oturumu olduğunu, ne kadar yetki taşıdığını, hatta bir oturum belirteci mi yoksa bir dil tercihi mi olduğunu söylemez. Aracı uygulamayı bilmez; çerezin değerini çözmeye kalksaydı uygulamayı bilmiş olurdu.

Bunun doğrudan bir sonucu var: aracı, çerezin varlığından yanıtın kişiye özel olduğunu çıkaramaz. Çıkarsaydı, yalnız bir dil tercihi taşıyan çerez yüzünden paylaşılabilir bir yanıtı saklamaktan vazgeçerdi. Tersini de yapamaz: çerezin yokluğundan yanıtın paylaşılabilir olduğunu çıkaramaz, çünkü sunucu kimliği başka bir alandan da okumuş olabilir.

Karar bu yüzden çerezde değil, yanıttaki imdedir. Sunucu ne bildirirse aracı onu bilir. Ortak kurgunun kişiye özel imi tam olarak bu bildirimdir ve iletide görünen tek kişiye özellik göstergesidir. Çerezin kendisi ölçüme bir karar eklemez; ölçüme giren şey çerezin hangi iletilerde bulunduğudur, ne taşıdığı değil.

Ömür niteliği de aynı sınıfa girer. Max-Age verilmiş bir çerez ile oturumluk bir çerez arasındaki fark istemcinin çerezi ne kadar saklayacağıdır; aracının o iletiden alacağı karar ikisinde de aynıdır. Aracı çerezin ne zaman düşeceğini bilmez ve bilmesi gerekmez.

İki Ayrı Kural

Çerezle ilgili iki karar vardır ve karıştırılmaları en sık görülen kusurdur.

Kapsam kuralı isteği ilgilendirir: çerez hangi iletilerde taşınır? Bunu Domain ve Path belirler ve kararı istemci verir. İm kuralı yanıtı ilgilendirir: saklanan yanıt kime gider? Bunu Cache-Control ve Vary belirler ve kararı sunucu bildirir, aracı uygular.

İkisi bağımsızdır. Kapsam doğru kurulmuş bir çerez, imi konmamış bir yanıtla birlikte gidebilir; o zaman çerez doğru yere gitmiştir ama yanıt yanlış kişiye verilebilir. Tersi de olur: im doğru konmuş bir yanıt, kapsamı gereğinden geniş bir çerezle birlikte gidebilir.

Ölçümün varsayımları:

  • HA41 — Kırk alışveriş ortak kurgudan üretilir; kâhin kurguyu biz ürettiğimiz için bilinir ve her alışverişte yanıtın gerçekten kişiye özel olup olmadığını söyler.
  • HA42 — Üç kapsam kuralı denenir: yalnız oturum yolu, ölçüm ve oturum yolu öneki, konağın tümü. Kapsam kuralı yalnız yola bakar; kural kâhini kullanmaz.
  • HA43 — Kişiye özel im, iletide görünen tek bildirimdir. Sunucu kimi kişiye özel yanıtta imi koymayı atlar; iletide yazanı doğrulayan hiçbir şey yoktur.
  • HA44 — Aracı imi gördüğünde paylasilabilir ve saklanabilir kararlarını fazladan gidiş–dönüş olmadan alır; görmediğinde ikisini de alamaz ve sunucuya bir tur daha atar.
  • HA45 — Bayt sayımı alan adı, değer ve ayraç uzunluğundan hesaplanır; ölçüm bir ağ ölçümü değil, ileti içeriğinin sayımıdır.

Ölçüm

"""Cerez kapsami ve durum tasima: aracinin ozel imden aldigi karar.

Bolum 1 - kapsam kurali cerezi hangi iletilere ilistiriyor.
Bolum 2 - im alani gorunurken ve zarfa alinmisken karar tablosu.
"""
TOHUM = 20260809
GUVENLI = {"GET", "HEAD"}
ETKISIZ = {"GET", "HEAD", "PUT", "DELETE"}
YONTEMLER = ["GET", "GET", "GET", "HEAD", "POST", "PUT", "DELETE"]
YOLLAR = ["/olcum/kuzey", "/olcum/yamac", "/ozet", "/kayit", "/oturum"]
KARARLAR = ("saklanabilir", "paylasilabilir", "taze", "yinelenebilir",
            "yonlendirilebilir")


def uretec(tohum):
    d = tohum % 2147483646 + 1

    def r(n):
        nonlocal d
        d = (d * 48271) % 2147483647
        return d % n
    return r


def alisverisler(sayi=40):
    r, liste = uretec(TOHUM), []
    for i in range(sayi):
        yontem, yol = YONTEMLER[r(7)], YOLLAR[r(5)]
        ozel = yol == "/oturum" or r(5) == 0
        degisti = r(3) == 0
        liste.append({"no": i + 1, "yontem": yontem, "yol": yol,
                      "ozel": ozel, "degisti": degisti,
                      "ozel_imi": ozel and r(4) != 0,
                      "damga_atladi": degisti and r(6) == 0})
    return liste


def kahin(a):
    return {"saklanabilir": a["yontem"] in GUVENLI and not a["ozel"],
            "paylasilabilir": not a["ozel"], "taze": not a["degisti"],
            "yinelenebilir": a["yontem"] in ETKISIZ,
            "yonlendirilebilir": True}


def ileti(a, gorunur):
    tam = {"yontem": a["yontem"], "yol": a["yol"], "konak": "istasyon.ornek",
           "ozel_imi": a["ozel_imi"],
           "dogrulayici": a["degisti"] and not a["damga_atladi"]}
    return {k: v for k, v in tam.items() if k in gorunur}


def bayt(i):
    return sum(len(k) + len(str(v)) + 4 for k, v in i.items())


def araci(i):
    k = {}
    if "yontem" in i:
        k["yinelenebilir"] = i["yontem"] in ETKISIZ
    if "ozel_imi" in i:
        k["paylasilabilir"] = not i["ozel_imi"]
        if "yontem" in i:
            k["saklanabilir"] = i["yontem"] in GUVENLI and not i["ozel_imi"]
    if "dogrulayici" in i:
        k["taze"] = not i["dogrulayici"]
    if "konak" in i:
        k["yonlendirilebilir"] = True
    return k


GORUNUR = {"açık": ("yontem", "yol", "konak", "ozel_imi", "dogrulayici"),
           "im zarfta": ("yontem", "yol", "konak", "dogrulayici")}
KAPSAM = {"oturum yolu": lambda a: a["yol"] == "/oturum",
          "ölçüm öneki": lambda a: a["yol"].startswith(("/olcum", "/oturum")),
          "konağın tümü": lambda a: True}
A = alisverisler()

print(f"alışveriş {len(A)} | karar {len(A) * len(KARARLAR)} | kişiye özel "
      f"{sum(a['ozel'] for a in A)} | imsiz kalan "
      f"{sum(a['ozel'] and not a['ozel_imi'] for a in A)}")
print("imsiz kalan alışverişler:",
      [(a["no"], a["yontem"], a["yol"]) for a in A
       if a["ozel"] and not a["ozel_imi"]])
print()
print("kapsam kuralı  çerez taşıyan  özel ve taşıyan  özel ama taşımayan"
      "  gereksiz taşıyan")
for ad, kural in KAPSAM.items():
    print(f"  {ad:12s} {sum(kural(a) for a in A):11d}"
          f" {sum(kural(a) and a['ozel'] for a in A):16d}"
          f" {sum(not kural(a) and a['ozel'] for a in A):19d}"
          f" {sum(kural(a) and not a['ozel'] for a in A):17d}")
print()
print("karar              açık: doğru yanlış   im zarfta: doğru yanlış alınamayan")
for karar in KARARLAR:
    s = {}
    for ad in GORUNUR:
        d = y = e = 0
        for a in A:
            g, v = kahin(a), araci(ileti(a, GORUNUR[ad]))
            if karar not in v:
                e += 1
            elif v[karar] == g[karar]:
                d += 1
            else:
                y += 1
        s[ad] = (d, y, e)
    print(f"  {karar:18s} {s['açık'][0]:5d} {s['açık'][1]:6d}"
          f" {s['im zarfta'][0]:16d} {s['im zarfta'][1]:6d}"
          f" {s['im zarfta'][2]:10d}")
print()
print("görünürlük   doğru  yanlış  alınamayan  fazladan tur   bayt")
for ad in GORUNUR:
    d = y = e = t = b = 0
    for a in A:
        g, v = kahin(a), araci(ileti(a, GORUNUR[ad]))
        eksik = False
        for karar in KARARLAR:
            if karar not in v:
                e += 1
                eksik = True
            elif v[karar] == g[karar]:
                d += 1
            else:
                y += 1
        t += 1 if eksik else 0
        b += bayt(ileti(a, GORUNUR[ad]))
    print(f"  {ad:10s} {d:5d} {y:7d} {e:11d} {t:13d} {b:6d}")
alışveriş 40 | karar 200 | kişiye özel 17 | imsiz kalan 2
imsiz kalan alışverişler: [(1, 'POST', '/kayit'), (34, 'POST', '/kayit')]

kapsam kuralı  çerez taşıyan  özel ve taşıyan  özel ama taşımayan  gereksiz taşıyan
  oturum yolu           11               11                   6                 0
  ölçüm öneki           24               12                   5                12
  konağın tümü          40               17                   0                23

karar              açık: doğru yanlış   im zarfta: doğru yanlış alınamayan
  saklanabilir          40      0                0      0         40
  paylasilabilir        38      2                0      0         40
  taze                  37      3               37      3          0
  yinelenebilir         40      0               40      0          0
  yonlendirilebilir     40      0               40      0          0

görünürlük   doğru  yanlış  alınamayan  fazladan tur   bayt
  açık         195       5           0             0   3524
  im zarfta    117       3          80            40   2859

Kapsamın Ödettiği

Üst tablo üç kapsam kuralını yan yana koyuyor ve hiçbiri sorunsuz değil.

Oturum yoluna daraltılmış kural çerezi 11 iletide taşıyor ve bu on birin hepsi gerçekten kişiye özel. Gereksiz taşıma 0. Bedeli sağdaki sütunda: kişiye özel olan 6 yanıt kapsamın dışında kalıyor. Kurgu bunu doğrudan söylüyor — kişiye özellik yolun kendisinden gelmiyor, sunucu /oturum dışındaki kimi yanıtı da kişiye özel üretiyor.

Konağın tümüne açılmış kural bu altısını kapatıyor: kapsam dışında kalan kişiye özel yanıt 0. Karşılığında çerez 23 iletide gereksiz taşınıyor — kırk alışverişin yarıdan fazlasında, hiçbir işe yaramadan. Aradaki ölçüm öneki kuralı ikisinin ortası: 12 gereksiz taşıma ve kapsam dışında kalan 5 kişiye özel yanıt.

Örüntü şudur: kapsam kuralı yola bakar, kişiye özellik ise yoldan çıkmaz. Kuralı genişletmek kapsam dışında kalanı azaltır ama gereksiz taşımayı doğrusal olarak büyütür. İkisini birden sıfırlayan bir yol yoktur, çünkü kapsam kuralının bilebileceği tek şey adrestir.

İmin Ödettiği

Alt tablolar ikinci kurala bakıyor. Kırk alışverişin 17’sinde yanıt kişiye özel, ve sunucu bunların 2’sinde imi koymayı atlamış. Aracı iki alışverişte de yanıtı paylaşılabilir sanıyor: paylasilabilir satırında 38 doğru, 2 yanlış.

saklanabilir satırı 40 doğru veriyor ve bu bir tesadüf değil. İmsiz kalan iki alışverişin ikisi de POST /kayit; ikisinin de yöntemi zaten güvenli değil. Eksik im, kararı ancak başka türlü saklanabilir olan bir yanıtta ödetir. Ölçümde bu koşulu sağlayan alışveriş yok, o yüzden bu satır temiz kalıyor. Aynı eksiklik güvenli yöntemli bir alışverişte olsaydı yanlış sayısı ikiden dörde çıkardı.

İki yanlış, iki yüz kararlık bir kümede 0,0100’lük bir paydır. Bu kümede ölçülebilen en küçük fark 1/200 = 0,0050’dir; iki yanlış onun iki katıdır ve ölçüm bandının içindedir. Bundan küçük bir fark bu kümeyle savunulamaz.

Son tabloda açık rejim 195 doğru, 5 yanlış, 0 alınamayan veriyor. Beş yanlışın 2’si buradaki eksik imden geliyor; kalan üçü taze satırında duruyor ve bambaşka bir alandan, doğrulayıcı damgasından kaynaklanıyor. O alan bu derste ölçülmüyor.

Yanlış Kurulmuş Kapsam ve Daraltmalar

Kapsamın geniş kurulması bir saldırı değil, bir yapılandırma kusurudur: kural yazılmış, sözdizimi doğru, çerez çalışıyor ve hiçbir belirti vermiyor. Sayılan üç yüzey ve her birini kapatan alan şunlardır.

Birinci yüzey — gereksiz taşıma. Konağın tümüne açılmış kapsamda çerez 23 iletide hiçbir işe yaramadan taşınıyor. Bu iletilerin her biri aracının önünden geçiyor ve aracı çerez alanını okuyabiliyor. Daraltma: Path niteliği oturum yoluna çekilirse gereksiz taşıma 0’a iner; bedeli, kapsam dışında kalan 6 kişiye özel yanıttır. Domain niteliğinin verilmemesi kapsamı tek konağa bağlar; verilmesi onu alt adlara açar. SameSite niteliği kapsamı yola göre değil, isteği başlatan bağlama göre daraltır ve Path daraltmasının kapatamadığı bir yönü kapatır: aynı yola giden ama başka bir kaynaktan doğan istek.

İkinci yüzey — imsiz saklanan yanıt. İki alışverişte aracı yanlış paylasilabilir kararı veriyor. Böyle bir yanıtın paylaşılan bir önbelleğe konması, kişiye özel bir kopyanın başka bir isteğe verilmesi demektir. Daraltma: yanıta Cache-Control: private konması kararı doğrulur; Vary: Cookie ise saklanan kopyayı Cookie alanına bağlar ve aynı adresin kopyalarını birbirinden ayırır. İkisi de sunucunun bildirimidir ve konmadıklarında aracı bunu anlayamaz.

Üçüncü yüzey — aracının imi görmesi. Aracı hangi iletinin kişiye özel olduğunu okuyor; bu, kararları gidiş–dönüşsüz almasının koşulu. Daraltma: im alanı taşıma zarfına alınırsa aracı onu göremez. Son tablodaki im zarfta satırı bedeli veriyor: 80 karar ortadan uçlara taşınıyor, kırk alışverişin kırkında birer tur daha atılıyor ve bayt 3524’ten 2859’a iniyor. Kazanç ise yanlış sayısının 5’ten 3’e inmesidir — aracının alamadığı karar, yanlış alamadığı karardır.

Özet

  • Çerez, durumu istemcide tutarak durumsuz protokolde durum taşır; nitelikler yanıtta Set-Cookie ile gider, geri dönüşte yalnız ad–değer çifti Cookie alanında taşınır.
  • Kapsam kuralı çerezin hangi iletide taşınacağını, im kuralı saklanan yanıtın kime gideceğini belirler; ikisi bağımsızdır ve ayrı ayrı yanlış kurulabilir.
  • Üç kapsam kuralı sırasıyla 11, 24 ve 40 ileti taşır; kapsam genişledikçe dışarıda kalan kişiye özel yanıt 6’dan 0’a iner, gereksiz taşıma 0’dan 23’e çıkar.
  • Kırk alışverişin 17’si kişiye özel, 2’sinde im konmamış; aracı iki yanlış paylasilabilir kararı verir. saklanabilir temiz kalır çünkü o iki alışverişin yöntemi zaten güvenli değildir.
  • İm alanı taşıma zarfına alındığında yanlış 5’ten 3’e iner ama 80 karar uçlara taşınır ve kırk tur borcu doğar; gizlemenin bedeli budur.

Sonraki Adım

Çerez bir başlık alanıdır ve kapsamı içindeki her istekte yeniden gönderilir. Kırk alışverişte konak adı kırk kez, yöntem kırk kez, çerez kapsamı ne kadarsa o kadar kez tekrarlanır — hepsi aynı bağlantı üzerinde, hepsi baştan yazılarak. Sonraki ders bu tekrarın nasıl paketlendiğine bakar: metin satırından ikili çerçeveye geçiş aracıya ne kazandırır, başlık sıkıştırması hangi alanı onun için okunmaz hâle getirir ve okunmayan alanın kararı nereye taşınır.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat