---
title: 'Rota Koruma'
source: 'https://academia.sh/tr/kurslar/frontend-mimarisi/rota-koruma'
course: 'Uygulama Mimarisi: Yönlendirme, Durum ve Veri'
language: tr
updated: '2026-08-17T18:09:21+00:00'
license: 'CC BY-SA 4.0'
---

# Rota Koruma

Yetkiye bağlı erişim; yol koruyucularının rota ağacında kalıtılması, izin–yönlendir–beklet kararları, bilinmeyen kimlik durumunun ayrı ele alınması, dönüş adresinin doğrulanması ve istemci denetiminin sınırı.

Adres artık hangi kaynağın hangi görünümünün istendiğini eksiksiz taşıyor. Taşımadığı tek
şey, kullanıcının o kaynağı görmeye hakkı olup olmadığı. Kuzey Yamaç Ölçüm İstasyonu
uygulamasında istasyon ayarları ekranı yalnız yetkili kullanıcılara, ölçüm girişi yalnız
oturum açmış kullanıcılara açık.

Bağlantıyı gizlemek çözüm değildir: adres çubuğuna elle yazılan bir yol da eşleyiciye
ulaşır. Karar, eşleşme ile görünümün kurulması arasında verilmelidir. Bu ders o karar
noktasını, kararın türlerini ve istemci tarafında verilen kararın neyi sağlayıp neyi
sağlamadığını ele alır.

## Yol Koruyucu

**Yol koruyucu**, bir rotanın görünümü kurulmadan önce çalışan ve üç yanıttan birini veren
işlevdir. Girdisi eşleşen rota ile o anki kimlik bilgisidir; çıktısı bir karardır.

**İzin**, görünümün kurulmasına engel olmaz. **Yönlendir**, gezinmeyi başka bir adrese
çevirir. **Beklet**, kararın henüz verilemediğini söyler; kimlik bilgisi gelene kadar ne
hedef görünüm ne de yönlendirme kurulur.

Koruyucular rota ağacında **kalıtılır**. Bir düğüme konan koruyucu, o düğümün altındaki
tüm rotalar için geçerlidir. İç İçe Rotalar ve Düzenler dersindeki yolsuz düzen
düğümlerinin ikinci kullanımı buydu: aynı erişim koşulunu paylaşan rotalar tek bir üst
düğümün altında toplanır ve koşul bir kez yazılır.

Bir rotanın koruyucuları kökten yaprağa doğru sıralanmış bir zincir oluşturur ve sırayla
çalıştırılır. **İlk reddeden kararı verir**; kalan koruyucular çalışmaz. Sıra rastgele
değildir: oturum koşulu rol koşulundan önce gelir, çünkü rolü sorabilmek için önce
kullanıcının kim olduğunun bilinmesi gerekir.

```js
// yol-koruyucu.mjs — kalitilan koruyucu zinciri, karar turleri ve donus adresinin dogrulanmasi
const KORUYUCU = {
  oturum: (k) => k.durum === "bilinmiyor" ? { karar: "beklet" }
    : k.durum === "acik" ? { karar: "izin" }
      : { karar: "yonlendir", hedef: "/oturum" },
  yonetici: (k) => k.rol === "yonetici" ? { karar: "izin" }
    : { karar: "yonlendir", hedef: "/yetkisiz", kayitDegistir: true },
  anonim: (k) => k.durum === "acik" ? { karar: "yonlendir", hedef: "/istasyon", kayitDegistir: true }
    : { karar: "izin" },
};

// Koruyucular rota agacinda kalitilir: ustteki dugumunki alt agacin tumune uygulanir.
const AGAC = [
  { yol: "/", koruyucu: [] },
  { yol: "/oturum", koruyucu: ["anonim"] },
  { yol: "/istasyon", koruyucu: ["oturum"] },
  { yol: "/istasyon/:kimlik/olcum", koruyucu: ["oturum"] },
  { yol: "/istasyon/:kimlik/ayar", koruyucu: ["oturum", "yonetici"] },
];

const TABAN = "https://ornek.gecerli";

function degerlendir(rota, kullanici, istenenAdres) {
  for (const ad of rota.koruyucu) {
    const sonuc = KORUYUCU[ad](kullanici);
    if (sonuc.karar === "izin") continue;
    if (sonuc.karar === "beklet") return { karar: "beklet", koruyucu: ad };
    const hedef = sonuc.hedef === "/oturum"
      ? `/oturum?donus=${encodeURIComponent(istenenAdres)}`
      : sonuc.hedef;
    return { karar: "yonlendir", koruyucu: ad, hedef, kayitDegistir: sonuc.kayitDegistir ?? true };
  }
  return { karar: "izin" };
}

const kullanicilar = [
  { ad: "yukleniyor", durum: "bilinmiyor", rol: null },
  { ad: "konuk", durum: "kapali", rol: null },
  { ad: "gozlemci", durum: "acik", rol: "gozlemci" },
  { ad: "yonetici", durum: "acik", rol: "yonetici" },
];

console.log("-- karar tablosu --");
for (const k of kullanicilar) {
  for (const rota of AGAC) {
    const istenen = rota.yol.replace(":kimlik", "kuzey-yamac");
    const s = degerlendir(rota, k, istenen);
    console.log([
      k.ad.padEnd(11), istenen.padEnd(30), s.karar.padEnd(10),
      (s.hedef ?? "-").padEnd(48), s.koruyucu ? `(${s.koruyucu})` : "",
    ].join(" ").trimEnd());
  }
}

// Donus adresi kullanicidan gelir; ac yonlendirmeyi onlemek icin dogrulanir.
function donusuCoz(ham) {
  if (ham === null) return "/istasyon";
  let coz;
  try { coz = new URL(ham, TABAN); } catch { return "/istasyon"; }
  if (coz.origin !== TABAN) return "/istasyon";
  if (!ham.startsWith("/") || ham.startsWith("//")) return "/istasyon";
  return coz.pathname + coz.search;
}

console.log("-- donus adresinin dogrulanmasi --");
for (const ham of [
  "/istasyon/kuzey-yamac/ayar?olcum=nem",
  "https://kotu.ornek/topla",
  "//kotu.ornek/topla",
  "istasyon/kuzey-yamac",
  "/istasyon/../../etc",
  null,
]) console.log(JSON.stringify(ham).padEnd(40), "->", donusuCoz(ham));
```

```
-- karar tablosu --
yukleniyor  /                              izin       -
yukleniyor  /oturum                        izin       -
yukleniyor  /istasyon                      beklet     -                                                (oturum)
yukleniyor  /istasyon/kuzey-yamac/olcum    beklet     -                                                (oturum)
yukleniyor  /istasyon/kuzey-yamac/ayar     beklet     -                                                (oturum)
konuk       /                              izin       -
konuk       /oturum                        izin       -
konuk       /istasyon                      yonlendir  /oturum?donus=%2Fistasyon                        (oturum)
konuk       /istasyon/kuzey-yamac/olcum    yonlendir  /oturum?donus=%2Fistasyon%2Fkuzey-yamac%2Folcum  (oturum)
konuk       /istasyon/kuzey-yamac/ayar     yonlendir  /oturum?donus=%2Fistasyon%2Fkuzey-yamac%2Fayar   (oturum)
gozlemci    /                              izin       -
gozlemci    /oturum                        yonlendir  /istasyon                                        (anonim)
gozlemci    /istasyon                      izin       -
gozlemci    /istasyon/kuzey-yamac/olcum    izin       -
gozlemci    /istasyon/kuzey-yamac/ayar     yonlendir  /yetkisiz                                        (yonetici)
yonetici    /                              izin       -
yonetici    /oturum                        yonlendir  /istasyon                                        (anonim)
yonetici    /istasyon                      izin       -
yonetici    /istasyon/kuzey-yamac/olcum    izin       -
yonetici    /istasyon/kuzey-yamac/ayar     izin       -
-- donus adresinin dogrulanmasi --
"/istasyon/kuzey-yamac/ayar?olcum=nem"   -> /istasyon/kuzey-yamac/ayar?olcum=nem
"https://kotu.ornek/topla"               -> /istasyon
"//kotu.ornek/topla"                     -> /istasyon
"istasyon/kuzey-yamac"                   -> /istasyon
"/istasyon/../../etc"                    -> /etc
null                                     -> /istasyon
```

Tablonun her satırı bir çift karardır: kim, nereye. Gözlemci ölçüm geçmişini görür ama
ayarlara giremez; yönetici ikisine de girer. Kök yol ve oturum ekranı koruyucusuz ya da
ters koruyuculudur.

## Ters Koruyucu

`anonim` koruyucusu diğerlerinin tersini yapar: oturumu **açık olan** kullanıcıyı oturum
ekranından uzaklaştırır. Bunu yapmayan bir uygulamada, oturum açmış kullanıcı geri
düğmesiyle oturum ekranına döner ve orada ne yapacağını bilmez; yeniden oturum açmaya
kalkarsa kimlik akışı iki kez çalışır.

Aynı ters mantık kayıt, parola sıfırlama ve karşılama akışları için de geçerlidir.

## Bilinmeyen Kimlik

Üçüncü karar türü, çıktının ilk beş satırında görülür. Uygulama yeni yüklendiğinde oturumun
açık olup olmadığı henüz bilinmez: bu bilgi ya bir istekle sunucudan gelir ya da yerel bir
kayıttan okunur. Her ikisi de zaman alır.

Bu aralıkta yapılan en yaygın hata, bilinmeyeni **yetkisiz saymaktır**. Sonucu tanıdıktır:
kullanıcı korunan bir sayfayı yeniler, bir an oturum ekranını görür, kimlik bilgisi
gelince asıl sayfaya döner. Ekranın bu şekilde iki kez değişmesi yalnız rahatsız edici
değildir; adres de iki kez değişmiş, geçmişe gereksiz kayıt girmiş olabilir.

Doğru davranış, kararı ertelemektir. Beklet yanıtı alan yönlendirme, kimlik bilgisi gelene
kadar ne hedef görünümü ne de oturum ekranını kurar; yerinde bir yükleniyor göstergesi
bırakır. Kimlik geldiğinde koruyucu yeniden çalıştırılır ve gerçek karar verilir.

Bekletmenin bir sınırı olmalıdır. Kimlik isteği başarısız olursa karar sonsuza kadar
ertelenemez; başarısızlık yetkisizlikle aynı sonuca bağlanır ve kullanıcıya nedeni
söylenir.

## Dönüş Adresi

Konuk kullanıcı korunan bir adrese gittiğinde oturum ekranına gönderilir. Oturum açtıktan
sonra karşılama ekranına düşmesi, gitmek istediği yeri unutmak demektir. Bu nedenle
istenen adres yönlendirmenin sorgusuna yazılır ve oturum açıldıktan sonra oradan okunur.

Bu parametre kullanıcının denetimindedir. Bir saldırgan `donus` değerine kendi adresini
koyup bağlantıyı paylaşabilir; kullanıcı tanıdığı bir sitede oturum açar ve hemen ardından
başka bir yere gönderilir. Bu kusurun adı **açık yönlendirmedir** ve önlemi tek cümledir:
dönüş adresi kullanılmadan önce uygulamanın kendi kaynağına ait olduğu doğrulanır.

Çıktının son bölümü doğrulamanın ne yakaladığını gösterir. Tam nitelikli dış adres
reddedilir. Eğik çizgiyle başlayan protokolsüz adres — tarayıcının aynı protokolle dış bir
konağa gitmesini sağlayan biçim — reddedilir; bu, yalnız ilk karakteri sınayan bir denetimin
kaçırdığı durumdur. Göreli adres de reddedilir, çünkü hangi tabana göre çözüleceği
belirsizdir. Geriye yalnız uygulama içi yollar kalır ve bunlar çözülürken normalleştirilir.

Aynı sınama, adresi kullanıcıdan alan her yerde geçerlidir: sorguda taşınan hedef adresler,
bildirim bağlantıları, hata sayfasındaki dönüş düğmeleri.

## Yönlendirme Geçmişe Nasıl Yazılır

Koruyucunun ürettiği yönlendirme, kullanıcının **istediği** bir gezinme değildir. Bu
nedenle geçmişe yeni bir kayıt eklemez, o anki kaydın yerine geçer. Aksi hâlde kullanıcı
oturum ekranından geri düğmesine bastığında korunan adrese döner, koruyucu yeniden çalışır
ve onu tekrar oturum ekranına gönderir — geri düğmesi işlemez hâle gelir.

Örnekteki kararlar bu nedenle `kayitDegistir` bayrağı taşır. Geçmiş ve Konum dersinde
kurulan ayrım burada doğrudan uygulanır: kullanıcının geri dönmek isteyeceği durumlar
eklenir, ara adresler değiştirilir.

## İstemci Denetiminin Sınırı

Bu dersin kurduğu her şey **arayüz kararıdır**, güvenlik sınırı değildir. Üç gerekçe bunu
gösterir.

Koruyucunun kodu kullanıcının makinesinde çalışır ve okunabilir; rol adları, koşullar,
gizli rotaların yolları paketin içindedir. Kullanıcı koruyucuyu çalıştırmayabilir: adresi
doğrudan istemek, isteği elle üretmek ya da yanıtı değiştirmek elindedir. Korunan görünümün
kullandığı veri de yine bir istekle alınır; görünümü gizlemek veriyi gizlemez.

Bu nedenle **her korunan işlem sunucuda yeniden yetkilendirilir**. İstemci tarafı koruma,
yetkisiz bir kullanıcının boş bir ekranla ya da bir hata yığınıyla karşılaşmasını önler;
verinin korunmasını sağlamaz.

Aynı ayrım gizli bilgi için de geçerlidir. Rol bilgisine göre bir menü ögesini gizlemek
kabul edilebilir; ancak yalnız yöneticinin görmesi gereken bir veri, gizlenmiş bir bileşenin
içine konup istemciye gönderilemez. Gönderilen her şey görülebilir.

## Özet

- Yol koruyucu, eşleşme ile görünümün kurulması arasında çalışır ve izin, yönlendir ya da
  beklet kararlarından birini verir; koruyucular rota ağacında kalıtılır, zincir hâlinde
  sırayla çalışır ve ilk reddeden karar verir.
- Kimliğin henüz bilinmediği durum yetkisizlikten ayrılır; karar ertelenir, ama erteleme
  başarısızlık durumunda sonlandırılır.
- Ters koruyucu, oturumu açık kullanıcıyı oturum ve kayıt ekranlarından uzaklaştırır.
- Dönüş adresi kullanıcı girdisidir; uygulamanın kendi kaynağına ait olduğu doğrulanmadan
  kullanılırsa açık yönlendirme kusuru doğar.
- Koruyucunun ürettiği yönlendirme geçmişe kayıt eklemez, o anki kaydı değiştirir.
- İstemci tarafı koruma bir arayüz kararıdır; her korunan işlem ve veri sunucuda yeniden
  yetkilendirilir.

## Sonraki Adım

Yönlendirme artık hangi ekranın kime açık olduğunu biliyor. Bilmediği şey, o ekranın
kodunun ne zaman indirileceği. Şu anda uygulamanın bütün ekranları — istasyon listesi,
ayarlar formu, ölçüm grafiği, oturum akışı — tek bir pakette birlikte iniyor. Kullanıcı
yalnız oturum açmak için gelse bile yönetici ayar ekranının kodunu indiriyor. Rota ağacı
bu bölünmeyi yapmak için gereken bilgiyi zaten taşıyor: hangi bileşenin hangi yolda
kullanıldığı tanımın içinde yazılı. Sonraki ders paketi rota sınırlarından bölmeyi, ortak
parçaların yinelenmesini önlemeyi ve bölünmenin getirdiği bekleme ile hata durumlarını ele
alır.
