---
title: 'Kimlik Doğrulama ve Yetkilendirme Ayrımı'
source: 'https://academia.sh/tr/kurslar/kimlik-ve-yetki/kimlik-dogrulama-ve-yetkilendirme-ayrimi'
course: 'Kimlik Doğrulama ve Yetkilendirme'
language: tr
updated: '2026-08-17T18:06:48+00:00'
license: 'CC BY-SA 4.0'
---

# Kimlik Doğrulama ve Yetkilendirme Ayrımı

İsteğin arkasındaki asılın belirlenmesi ile o asılın ne yapabileceğine karar verilmesinin iki ayrı soru olduğunun gösterilmesi: yalnız birincisini soran sunucunun gözlenebilir sonucu, 401 ile 403 ayrımı ve kararın öntanımlı ret üzerine kurulması.

Önceki kurs boyunca ödünç servisinin sözleşmesi kuruldu: hangi adres hangi kaynağı verir,
hangi yöntem neyi değiştirir, hata hangi biçimde bildirilir, sözleşme nasıl belgelenir ve
sınanır. Bütün bu kararlar tek bir soruyu hiç sormadı: bu isteği **kim** yolluyor? Sahte
sunucu her isteğe aynı yanıtı verdi, sözleşme sınaması her etkileşimi aynı ayrıcalıkla
çalıştırdı. Sözleşme, çağıranın kim olduğundan bağımsız yazılmıştı.

Gerçek serviste bu bağımsızlık sürmez. Ödünç kaydını üye kendisi için okuyabilir, gecikme
raporunu yalnız personel görebilir, bir üyenin cezasını yalnız şube yöneticisi silebilir. Bu
cümlelerin her biri iki ayrı bilgi içerir: isteğin arkasındaki kimliğin ne olduğu ve o
kimliğin ne yapmaya izinli olduğu. Bu kurs bu iki bilgiyi ayırmakla başlar, çünkü ikisini
tek soru sanan bir sunucu her zaman aynı biçimde bozulur.

## İki Ayrı Soru

**Kimlik doğrulama** (authentication) "sen kimsin?" sorusunu yanıtlar. Sunucu, isteğin
taşıdığı **kimlik bilgisinden** (credential) yola çıkarak isteğin arkasındaki **asılı**
(principal) belirler. Asıl bir kişi olabilir, bir servis hesabı olabilir, bir raf terminali
olabilir. Bu adımın çıktısı tek bir şeydir: bir kimlik ya da hiç.

**Yetkilendirme** (authorization) "bunu yapabilir misin?" sorusunu yanıtlar. Girdisi asıl,
istenen eylem ve eylemin hedefidir; çıktısı bir karardır: izin ver ya da reddet. Bu adım
kimliği kendisi bulmaz, birinci adımın bulduğunu kullanır.

Sıra tersine çevrilemez. Kimliği bilmeden yetki kararı verilemez, çünkü kararın girdisi
eksiktir. Ama tersi sık görülür: kimlik doğru belirlenir, sonra yetki sorusu hiç sorulmaz.
Sunucu asılın var olmasını yeterli sayar ve "kayıtlı olan her şeyi yapabilir" kuralını
farkında olmadan uygular. Bu kuralın sonucu kodda görünmez; ancak istekler çalıştırılınca
görünür.

## Yalnız Birinci Sorunun Sorulduğu Sunucu

Aşağıdaki sunucu üç uç sunar ve kimliği doğru belirler: tanınmayan bir kimlik bilgisi 401
alır. Yetki denetimi ise bir bayrağın arkasındadır; bayrak verilmediğinde ikinci soru hiç
sorulmaz.

```js
// odunc.mjs — odunc servisi; kimlik dogrulama var, yetkilendirme secmeli
// Kullanim: node odunc.mjs <port> [yetki]
//   yetki: verilirse rol denetimi de calisir
import { createServer } from "node:http";

const PORT = Number(process.argv[2] ?? 8501);
const YETKI = process.argv[3] === "yetki";

// Kimlik bilgisi -> asil (principal). Bu esleme sonraki derslerin konusu;
// burada kimligin belirlenmis oldugu varsayiliyor.
const KIMLIKLER = new Map([
  ["k-uye-1001", { kod: "U-1001", ad: "Deniz Aral", rol: "uye" }],
  ["k-personel-7", { kod: "P-0007", ad: "Selin Kaya", rol: "personel" }],
  ["k-yonetici-2", { kod: "Y-0002", ad: "Ahmet Ünal", rol: "sube-yoneticisi" }],
]);

const ODUNC = new Map([
  ["O-1", { id: "O-1", uye: "U-1001", isbn: "978-0262033848", sonTarih: "2026-03-20", durum: "acik" }],
  ["O-2", { id: "O-2", uye: "U-1042", isbn: "978-0201896831", sonTarih: "2026-02-11", durum: "gecikmis" }],
]);

// Uc -> o ucu cagirabilecek roller
const IZIN = new Map([
  ["GET /odunc", ["uye", "personel", "sube-yoneticisi"]],
  ["GET /raporlar/gecikmeler", ["personel", "sube-yoneticisi"]],
  ["POST /cezalar/silme", ["sube-yoneticisi"]],
]);

createServer((istek, yanit) => {
  yanit.sendDate = false;
  const yol = istek.url.split("?")[0];
  const json = (kod, govde, baslik = {}) => {
    yanit.writeHead(kod, { "content-type": "application/json; charset=utf-8", ...baslik });
    yanit.end(JSON.stringify(govde));
  };

  // 1. soru: kim? — kimlik bilgisi yoksa ya da taninmiyorsa 401
  const bilgi = (istek.headers.authorization ?? "").replace(/^Kimlik /, "");
  const asil = KIMLIKLER.get(bilgi);
  if (!asil) {
    return json(401, { hata: "kimlik dogrulanamadi" }, { "www-authenticate": 'Kimlik realm="odunc"' });
  }

  // Ucun adi
  const uc = yol.startsWith("/odunc/") ? "GET /odunc"
    : yol === "/raporlar/gecikmeler" ? "GET /raporlar/gecikmeler"
    : yol === "/cezalar/silme" ? "POST /cezalar/silme"
    : null;
  if (!uc || !uc.startsWith(istek.method)) return json(404, { hata: "kaynak yok" });

  // 2. soru: ne yapabilir? — yalnizca YETKI acikken soruluyor
  if (YETKI && !IZIN.get(uc).includes(asil.rol)) {
    return json(403, { hata: "bu islem icin yetkiniz yok", rol: asil.rol, gerekli: IZIN.get(uc) });
  }

  if (uc === "GET /odunc") {
    const kayit = ODUNC.get(yol.slice("/odunc/".length));
    return kayit ? json(200, kayit) : json(404, { hata: "kayit yok" });
  }
  if (uc === "GET /raporlar/gecikmeler") {
    return json(200, { gecikmis: [...ODUNC.values()].filter((k) => k.durum === "gecikmis") });
  }
  return json(200, { silindi: true, isleyen: asil.kod });
}).listen(PORT, "127.0.0.1", () => console.log(`odunc 127.0.0.1:${PORT} yetki=${YETKI}`));
```

Karar tablosunu okumak için her rolü her uçta deneyen küçük bir istemci yeter.

```js
// dizge.mjs — her rolun her uctan aldigi durum kodunu tablolar
// Kullanim: node odunc.mjs 8501 &  ve  node odunc.mjs 8502 yetki &  calisirken
//           node dizge.mjs 8501    /    node dizge.mjs 8502
const PORT = Number(process.argv[2] ?? 8501);
const TABAN = `http://127.0.0.1:${PORT}`;

const ROLLER = [["uye", "k-uye-1001"], ["personel", "k-personel-7"], ["yönetici", "k-yonetici-2"], ["tanımsız", "k-yok"]];
const UCLAR = [["GET", "/odunc/O-1"], ["GET", "/raporlar/gecikmeler"], ["POST", "/cezalar/silme"]];

console.log("rol".padEnd(10) + UCLAR.map(([y, u]) => `${y} ${u}`.padEnd(26)).join(""));
for (const [ad, bilgi] of ROLLER) {
  const kodlar = [];
  for (const [yontem, yol] of UCLAR) {
    const cevap = await fetch(TABAN + yol, { method: yontem, headers: { authorization: `Kimlik ${bilgi}` } });
    kodlar.push(String(cevap.status).padEnd(26));
  }
  console.log(ad.padEnd(10) + kodlar.join(""));
}
```

İki sunucu aynı anda ayağa kaldırılır; biri yetki denetimsiz, diğeri denetimli.

```bash
node odunc.mjs 8501 > /dev/null & DENETIMSIZ=$!
node odunc.mjs 8502 yetki > /dev/null & DENETIMLI=$!
sleep 1
echo "— yetki denetimi yok —"
node dizge.mjs 8501
echo "— yetki denetimi var —"
node dizge.mjs 8502
kill $DENETIMSIZ $DENETIMLI
```

```
— yetki denetimi yok —
rol       GET /odunc/O-1            GET /raporlar/gecikmeler  POST /cezalar/silme
uye       200                       200                       200
personel  200                       200                       200
yönetici  200                       200                       200
tanımsız  401                       401                       401
— yetki denetimi var —
rol       GET /odunc/O-1            GET /raporlar/gecikmeler  POST /cezalar/silme
uye       200                       403                       403
personel  200                       200                       403
yönetici  200                       200                       200
tanımsız  401                       401                       401
```

İlk tabloda dört satırın üçü aynıdır. Kimlik doğrulama çalışıyor: tanınmayan kimlik bilgisi
her uçta 401 alıyor. Denetimin verdiği tek ayrım "kayıtlı" ile "kayıtsız" arasındadır. Üye
kimliğiyle gelen bir istek gecikme raporunun tamamını okuyor ve bir cezayı siliyor; yanıtın
`isleyen` alanı silme işleminin U-1001 adına yapıldığını söylüyor.

Bu, kimlik doğrulamanın bir kusuru değildir; kimlik doğrulama görevini yapmıştır. Kusur,
yetki kararının hiç verilmemiş olmasıdır. İkinci tabloda aynı istekler 403 alır ve tablo
artık üç farklı satır içerir. Aradaki tek fark, isteği işleyen kodun ikinci soruyu sormasıdır.

## 401 ve 403 Ayrımı

İki durum kodu iki farklı soruya karşılık gelir ve birbirinin yerine kullanılamaz.

**401**, birinci sorunun yanıtsız kaldığını bildirir: kimlik bilgisi yok, biçimsiz ya da
tanınmıyor. Yanıt, kimliğin nasıl sunulacağını söyleyen `WWW-Authenticate` başlığını taşımak
zorundadır; bu başlık olmadan istemcinin ne yapacağı belirsiz kalır.

```bash
node odunc.mjs 8502 yetki > /dev/null & SUNUCU=$!
sleep 1
curl -s -D - -o /dev/null http://127.0.0.1:8502/cezalar/silme | head -3
kill $SUNUCU
```

```
HTTP/1.1 401 Unauthorized
content-type: application/json; charset=utf-8
www-authenticate: Kimlik realm="odunc"
```

**403**, birinci sorunun yanıtlandığını ama ikincisinin ret verdiğini bildirir. Kimlik
bellidir ve geçerlidir; eksik olan yetkidir. Aynı kimlik bilgisini yeniden yollamak sonucu
değiştirmez, çünkü sorun kimlik bilgisinde değildir.

```bash
node odunc.mjs 8502 yetki > /dev/null & SUNUCU=$!
sleep 1
curl -s -w ' %{http_code}\n' -X POST -H 'Authorization: Kimlik k-uye-1001' http://127.0.0.1:8502/cezalar/silme
kill $SUNUCU
```

```
{"hata":"bu islem icin yetkiniz yok","rol":"uye","gerekli":["sube-yoneticisi"]} 403
```

Bu ayrım istemcinin davranışını belirler. 401 alan istemci kimlik bilgisini tazeleyip yeniden
dener; 403 alan istemci yeniden denemez, kullanıcıya yetkisinin yetmediğini söyler. Kodları
karıştıran bir sunucu, 403 yerine 401 döndürerek istemciyi sonsuz bir tazeleme döngüsüne
sokar.

Üçüncü bir seçenek de vardır: bir kaynağın **varlığının** kendisi gizli bilgiyse, yetkisiz
isteğe 403 yerine 404 dönmek gerekebilir. 403, "böyle bir kaynak var ama sana kapalı" der ve
bu cümle bazı durumlarda söylenmemesi gereken bir bilgidir. Bu seçim bilinçli yapılmalıdır;
her yerde 404 dönmek de hata ayıklamayı sağır eder.

## Kararın Nerede Verildiği

Yetki kararının kod içinde bir **karar noktası** vardır. Yukarıdaki sunucuda bu nokta tek bir
`if` bloğudur ve isteği işleyen koddan önce gelir. İki özelliği önemlidir.

Birincisi, karar noktası **öntanımlı ret** üzerine kurulur. `IZIN` tablosunda karşılığı
olmayan bir uç, kimseye açık değildir. Bunun tersi olan kurulumda — "tabloda yasaklanmayan
her şey serbest" — tabloya eklenmeyi unutmuş her yeni uç, yazıldığı anda herkese açılır.
Yeni uç eklemek sık bir iştir; unutmak da öyle. Öntanımlı ret, unutmanın sonucunu erişim
açığından çalışmayan uca çevirir: sonuç yine hatadır ama gözlenebilir ve zararsız bir
hatadır.

İkincisi, karar noktası **tek** olmalıdır. Aynı kararın iki yerde verildiği bir kodda ikisi
zamanla ayrışır ve hangisinin geçerli olduğu ancak isteği çalıştırarak bulunur. Ara katman
zinciri — Sunucu Tarafı Temelleri kursunda kurulan yapı — bu tekliği sağlamanın doğal yeridir:
kimliği belirleyen katman isteğe asılı iliştirir, yetki katmanı o asıla bakar, iş mantığı
ikisini de yeniden hesaplamaz.

Bu iki soru, denetimin tamamı değildir. İkinci tablodaki `uye` satırında `GET /odunc/O-1`
hücresi 200'dür ve doğrudur: üyeler ödünç kaydı okuyabilir. Ama aynı üye başkasının kaydını
da okuyabilir.

```bash
node odunc.mjs 8502 yetki > /dev/null & SUNUCU=$!
sleep 1
curl -s -w ' %{http_code}\n' -H 'Authorization: Kimlik k-uye-1001' http://127.0.0.1:8502/odunc/O-2
kill $SUNUCU
```

```
{"id":"O-2","uye":"U-1042","isbn":"978-0201896831","sonTarih":"2026-02-11","durum":"gecikmis"} 200
```

U-1001 kimliğiyle gelen istek, U-1042 üyesinin kaydını aldı. Rol denetimi geçti çünkü soru
"üyeler ödünç kaydı okuyabilir mi?" biçiminde soruldu; sorulması gereken "bu üye **bu**
kaydı okuyabilir mi?" idi. Rol, eylem türünü yetkilendirir; nesnenin sahipliğini
yetkilendirmez. Bu ayrım Yetkilendirme Modelleri konusunun kendi başına bir dersidir; burada
yalnız şu tespit yeterlidir: yetki sorusu bir uç adına değil, bir asıl–eylem–nesne üçlüsüne
sorulur.

## Özet

- Kimlik doğrulama isteğin arkasındaki asılı belirler; yetkilendirme o asılın belirli bir
  eylemi yapıp yapamayacağına karar verir. İkincisinin girdisi birincisinin çıktısıdır.
- Yalnız kimlik doğrulayan bir sunucu "kayıtlı olan her şeyi yapabilir" kuralını uygular;
  bu kural kodda değil, erişim tablosunda görünür.
- 401 kimlik bilgisinin eksik ya da tanınmaz olduğunu bildirir ve `WWW-Authenticate`
  başlığını taşır; 403 kimliğin bilindiğini ama yetkinin yetmediğini bildirir.
- Kaynağın varlığı gizli bilgiyse yetkisiz isteğe 404 dönmek bilinçli bir seçenektir;
  varsayılan değildir.
- Karar noktası öntanımlı ret üzerine kurulur ve tektir; tabloya eklenmeyen uç kapalı kalır.
- Rol denetimi eylem türünü yetkilendirir, nesnenin sahipliğini yetkilendirmez; yetki sorusu
  asıl–eylem–nesne üçlüsüne sorulur.

## Sonraki Adım

Bu derste kimliğin nasıl belirlendiği bir eşleme tablosunun arkasına saklandı: istek bir
dizge taşıdı, sunucu onu bir asıla çevirdi. Gerçek bir kurulumda bu dizgenin nereden geldiği,
nasıl taşındığı ve ne kadar süre geçerli olduğu ayrı kararlardır. En eski ve en küçük yanıt,
HTTP'nin kendi içinde tanımlı temel şemadır: kullanıcı adı ve parola her istekte
`Authorization` başlığında taşınır. Sonraki ders bu şemayı çalıştırarak kurar, taşınan
değerin niçin şifrelenmiş sayılmadığını gösterir ve şemanın nerede yeterli, nerede yetersiz
kaldığını sınırlarıyla belirler.
