---
title: 'Öznitelik Tabanlı Erişim Denetimi'
source: 'https://academia.sh/tr/kurslar/kimlik-ve-yetki/oznitelik-tabanli-erisim-denetimi'
course: 'Kimlik Doğrulama ve Yetkilendirme'
language: tr
updated: '2026-08-17T18:06:48+00:00'
license: 'CC BY-SA 4.0'
---

# Öznitelik Tabanlı Erişim Denetimi

Kararın özne, nesne, eylem ve bağlam öznitelikleriyle verilmesi, ret önceliğinin kural birleştirmedeki rolü, aynı senaryo kümesinde öznitelik tabanlı modelin doğru ve yanlış kararları ve özniteliğin nereden okunduğunun sonucu.

Önceki dersin sekiz senaryosunda dört karar yanlış çıktı ve üçünün nedeni aynıydı: rol
tabanlı model isteğin bağlamını göremiyor. Kaydın sahibinin kim olduğu, personelin hangi
şubede çalıştığı, isteğin hangi saatte geldiği — bunların hepsi karar anında bilinen
bilgilerdir, ama izin adının içinde onlara yer yoktur.

**Öznitelik tabanlı erişim denetimi (attribute-based access control)** bu bilgileri kararın
girdisi hâline getirir. Kararı veren şey artık bir izin listesindeki üyelik değil, öznitelik
değerleri üzerinde çalışan bir kuraldır.

## Dört Öznitelik Kümesi

Model, karar anında dört kaynaktan öznitelik toplar.

**Özne öznitelikleri**, isteği yapanın kendisine aittir: kod, rol, çalıştığı şube, kıdem,
kimlik doğrulamanın hangi etmenlerle yapıldığı.

**Nesne öznitelikleri**, erişilmek istenen kayda aittir: türü, sahibi, ait olduğu şube,
gizlilik sınıfı, oluşturulma tarihi.

**Eylem**, yapılmak istenen işlemdir; rol tabanlı modeldekiyle aynı anlamı taşır.

**Bağlam öznitelikleri** ne özneye ne nesneye aittir; isteğin kendisine aittir: saat, ağ
konumu, isteğin geldiği aygıt, oturumun yaşı.

Kural, bu dört kümenin değerleri üzerinde bir koşuldur. "Kendi kaydını görüntüleyebilir"
kuralı, özne kodunun nesne sahibine eşitliğidir; şube kuralı iki şube özniteliğinin
eşitliğidir. Rol tabanlı modelde ifade edilemeyen şey bu eşitliklerdi, çünkü orada karar
kayda hiç bakmıyordu.

## Kuralların Birleştirilmesi

Birden çok kural aynı isteğe uyabilir ve sonuçları çelişebilir. Birleştirme kuralı bu
durumda ne olacağını söyler. Yerleşik seçim **ret önceliğidir**: eşleşen kurallardan biri
ret diyorsa karar rettir, izin diyen kuralların sayısı önemsizdir. Hiçbir kural eşleşmezse
karar yine rettir — izin, açıkça verilmesi gereken bir şeydir.

Aşağıdaki değerlendirici dört kuralı bu birleştirmeyle uyguluyor ve önceki dersin sekiz
senaryosunu yeniden karara bağlıyor. Son sütun, kararı hangi kuralın verdiğini gösteriyor.

```bash
cat > abac.mjs <<'EOF'
const OZNE = {
  "U-1001": { rol: "uye", sube: "S-02" }, "U-1002": { rol: "uye", sube: "S-02" },
  "U-1005": { rol: "uye", sube: "S-01" }, "P-2001": { rol: "gorevli", sube: "S-02" },
  "Y-3001": { rol: "sube_yoneticisi", sube: "S-02" },
};

// Onceki dersteki ortak senaryo kumesi.
const SENARYOLAR = [
  ["S1", "U-1001", "goruntule", "odunc:501",  { sahip: "U-1001", sube: "S-02" }, "10:15", true],
  ["S2", "U-1001", "goruntule", "odunc:502",  { sahip: "U-1002", sube: "S-02" }, "10:16", false],
  ["S3", "P-2001", "goruntule", "odunc:502",  { sahip: "U-1002", sube: "S-02" }, "10:20", true],
  ["S4", "P-2001", "goruntule", "odunc:503",  { sahip: "U-1005", sube: "S-01" }, "10:21", false],
  ["S5", "P-2001", "guncelle",  "odunc:502",  { sahip: "U-1002", sube: "S-02" }, "22:40", false],
  ["S6", "Y-3001", "sil",       "ceza:77",    { sahip: "U-1002", sube: "S-02" }, "11:05", true],
  ["S7", "U-1002", "goruntule", "liste:9",    { sahip: "U-1001", sube: "S-02" }, "12:00", true],
  ["S8", "U-1005", "goruntule", "liste:9",    { sahip: "U-1001", sube: "S-02" }, "12:01", false],
];

const mesaiIci = (saat) => saat >= "08:30" && saat <= "18:00";
const YAZAN = new Set(["guncelle", "olustur", "sil"]);

const KURALLAR = [
  { ad: "K1 kendi kaydi", etki: "izin",
    kosul: (o, e, n) => e === "goruntule" && n.sahip === o.kod },
  { ad: "K2 sube gorevlisi", etki: "izin",
    kosul: (o, e, n) => ["gorevli", "sube_yoneticisi"].includes(o.rol) &&
      n.sube === o.sube && ["goruntule", "guncelle", "olustur"].includes(e) },
  { ad: "K3 ceza silme", etki: "izin",
    kosul: (o, e, n) => o.rol === "sube_yoneticisi" && n.sube === o.sube &&
      e === "sil" && n.tur === "ceza" },
  { ad: "K4 mesai disi yazma", etki: "ret",
    kosul: (o, e, n, b) => YAZAN.has(e) && !mesaiIci(b.saat) && o.rol !== "sube_yoneticisi" },
];

function abac(ozneKod, eylem, nesneAdi, nesneOzn, saat) {
  const o = { kod: ozneKod, ...OZNE[ozneKod] };
  const n = { tur: nesneAdi.split(":")[0], ...nesneOzn };
  const b = { saat };
  const eslesen = KURALLAR.filter((k) => k.kosul(o, eylem, n, b));
  const ret = eslesen.find((k) => k.etki === "ret");
  const izin = eslesen.find((k) => k.etki === "izin");
  if (ret) return [false, `${ret.ad} (ret onceliklidir)`];
  if (izin) return [true, izin.ad];
  return [false, "eslesen kural yok"];
}

console.log("senaryo | ABAC | dogru | uyum | karari veren kural");
console.log("--------|------|-------|------|----------------------------");
let uyan = 0;
for (const [ad, ozne, eylem, nesne, ozn, saat, dogru] of SENARYOLAR) {
  const [karar, gerekce] = abac(ozne, eylem, nesne, ozn, saat);
  if (karar === dogru) uyan++;
  console.log(`${ad}      | ${(karar ? "izin" : "ret").padEnd(4)} | ` +
    `${(dogru ? "izin" : "ret").padEnd(5)} | ${(karar === dogru ? "+" : "-").padEnd(4)} | ${gerekce}`);
}
console.log(`\nABAC dogru karar: ${uyan}/${SENARYOLAR.length}`);
EOF
node abac.mjs
```

```text
senaryo | ABAC | dogru | uyum | karari veren kural
--------|------|-------|------|----------------------------
S1      | izin | izin  | +    | K1 kendi kaydi
S2      | ret  | ret   | +    | eslesen kural yok
S3      | izin | izin  | +    | K2 sube gorevlisi
S4      | ret  | ret   | +    | eslesen kural yok
S5      | ret  | ret   | +    | K4 mesai disi yazma (ret onceliklidir)
S6      | izin | izin  | +    | K3 ceza silme
S7      | ret  | izin  | -    | eslesen kural yok
S8      | ret  | ret   | +    | eslesen kural yok

ABAC dogru karar: 7/8
```

Rol tabanlı modelde yanlış çıkan dört karardan üçü düzeldi. S2 ve S4, sahiplik ve şube
özniteliklerinin karşılaştırılmasıyla; S5, bağlam özniteliğiyle. S8'in kararı da artık
doğru nedenle veriliyor: liste U-1005'in değil, dolayısıyla hiçbir kural eşleşmiyor.

Gerekçe sütunu modelin ikinci kazancıdır. Her karar, onu veren kuralın adıyla birlikte
üretilebilir; "neden reddedildi" sorusunun yanıtı kütüğe yazılabilir. Rol tabanlı modelde
bu yanıt "rolde o izin yoktu" cümlesinden ibaretti.

## Modelin Ulaşamadığı Yer

S7 hâlâ yanlış. U-1001, dokuz numaralı okuma listesini U-1002 ile paylaşmış; U-1002 bu
listeyi görebilmeli. Öznitelik tabanlı modelde bu kısıtı yazmanın yolu, paylaşımı bir
öznitelik hâline getirmektir: nesneye bir `paylasilanlar` alanı eklenir ve kural, özne
kodunun o listede olup olmadığına bakar.

Bu yol küçük ölçekte çalışır, iki yerde tıkanır. Birincisi geçişkenliktir: U-1002 listeyi
kendi çalışma grubuyla paylaşırsa, grubun üyeleri de erişmelidir. Öznitelik listesi bunu
ancak grubun tüm üyelerini tek tek içine alarak ifade eder ve grup değiştikçe her nesnenin
özniteliği güncellenmelidir. İkincisi dolaylılıktır: "şube yöneticisinin yönettiği şubede
çalışan personelin açtığı ödünç kayıtları" gibi bir kısıt, iki adım uzaklıktaki bir bağa
dayanır ve tek bir öznitelik alanına sığmaz.

Bu iki durum, kısıtın öznitelik değil **ilişki** olduğunun işaretidir. Sonraki dersin konusu
budur.

## Özniteliğin Kaynağı ve Tazeliği

Öznitelik tabanlı modelin işletimdeki asıl sorusu kuralların nasıl yazıldığı değil,
özniteliklerin nereden okunduğudur. İki seçenek vardır: değerler kimlik belirtecinin içinde
taşınır ya da karar anında kaydından okunur.

Belirteçten okumak hızlıdır ve ek sorgu gerektirmez. Bedeli, değerin belirtecin üretildiği
andaki değer olmasıdır. Aşağıdaki örnek, şube değiştiren bir görevlinin iki isteğini iki
kaynakla karara bağlıyor.

```bash
cat > tazelik.mjs <<'EOF'
const KAYIT = { "P-2001": { rol: "gorevli", sube: "S-01" } };   // 12:00'de S-02'den S-01'e gecti
const BELIRTEC = { kod: "P-2001", rol: "gorevli", sube: "S-02", uretim: "09:00" };

const kural = (o, n) => o.rol === "gorevli" && n.sube === o.sube;

const istekler = [
  ["odunc:502 (sube S-02)", { sube: "S-02" }, false],   // artik gormemeli
  ["odunc:503 (sube S-01)", { sube: "S-01" }, true],    // artik gormeli
];

console.log("oznitelik kaynagi        | " + istekler.map((i) => i[0]).join(" | "));
console.log("-------------------------|-----------------------|-----------------------");
for (const [ad, o] of [["belirtecten (09:00)", { ...BELIRTEC }],
                       ["kayittan (istek ani)", { kod: "P-2001", ...KAYIT["P-2001"] }]]) {
  const hucreler = istekler.map(([, n, dogru]) => {
    const karar = kural(o, n);
    return `${karar ? "izin" : "ret"} ${karar === dogru ? "(dogru)" : "(YANLIS)"}`.padEnd(21);
  });
  console.log((ad.padEnd(24) + " | " + hucreler.join(" | ")).trimEnd());
}
EOF
node tazelik.mjs
```

```text
oznitelik kaynagi        | odunc:502 (sube S-02) | odunc:503 (sube S-01)
-------------------------|-----------------------|-----------------------
belirtecten (09:00)      | izin (YANLIS)         | ret (YANLIS)
kayittan (istek ani)     | ret (dogru)           | izin (dogru)
```

Belirteçteki eski değer iki yönde birden yanlış karar üretiyor: görevlinin artık görmemesi
gereken kayda izin veriyor, görmesi gereken kaydı reddediyor. İkincisi bir destek talebi
olarak görünür ve düzeltilir; birincisi hiç görünmez.

Karar kuralı şudur: **kararı değiştiren öznitelik, değişebiliyorsa karar anında okunur.**
Belirteçte yalnız değişmeyen ya da belirteç ömrü içinde değişmesi kabul edilebilir
öznitelikler taşınır. Belirteç ömrü kısaldıkça bu ayrımın önemi azalır — yenileme
belirteçleri dersindeki ömür kararı, buradaki tazelik kararıyla aynı ödünleşimin iki
yüzüdür.

Kayıttan okumanın bedeli her istekte bir sorgudur. Bu maliyet, öznitelikleri istek başına
bir kez okuyup istek boyunca önbelleğe almakla sınırlanır; önbelleğin ömrü isteğin ömrünü
aşmamalıdır.

## Kuralların Denetlenebilirliği

Öznitelik tabanlı modelin kazandırdığı ifade gücü, bir maliyetle gelir: kuralların bir
arada ne yaptığını görmek zorlaşır. Rol tabanlı modelde bir hesabın etkin izin kümesi
hesaplanabiliyordu; öznitelik kurallarında böyle bir küme yoktur, çünkü karar isteğin
kendisine bağlıdır.

Bunun yerine iki denetim yordamı kullanılır.

**Senaryo kümesi.** Bu dersteki tablonun kendisi bir denetim aracıdır: bilinen istekler ve
beklenen yanıtlar bir küme hâlinde tutulur, kural her değiştiğinde küme yeniden
çalıştırılır. Uyum sütununda eksi çıkması, kuralın metnine bakmayı gerektirir.

**Kural kapsamı.** Hiçbir senaryoda eşleşmeyen bir kural ya gereksizdir ya da yanlış
yazılmıştır; her senaryoda eşleşen bir kural büyük olasılıkla fazla geniştir. Kuralların
kaç kez eşleştiği sayılabilir ve bu sayı kuralın yazılışı hakkında bilgi verir.

Üçüncü bir kural yazım disiplinidir: kurallar yan etkisiz olmalı, aynı girdide her zaman
aynı kararı üretmelidir. Karar sırasında kayıt yazan, dış servis çağıran ya da rastgele
değer kullanan bir kural, yeniden çalıştırılamaz ve denetlenemez.

## Özet

- Öznitelik tabanlı erişim denetimi kararı özne, nesne, eylem ve bağlam özniteliklerinden
  üretir; rol tabanlı modelde ifade edilemeyen sahiplik ve şube kısıtları burada eşitlik
  koşulu olarak yazılır.
- Kural birleştirmede ret önceliklidir ve hiçbir kural eşleşmezse karar rettir.
- Model her kararın gerekçesini üretebilir; bu, reddin nedeninin kütüğe yazılmasını mümkün
  kılar.
- Geçişken ve dolaylı bağlar öznitelik alanına sığmaz; bu kısıtlar öznitelik değil ilişki
  niteliğindedir.
- Kararı değiştiren öznitelik değişebiliyorsa karar anında okunur; belirteçte taşınan eski
  değer iki yönde birden yanlış karar üretir.

## Sonraki Adım

S7 iki derstir yanlış karara bağlanıyor. Paylaşılmış bir listenin erişilebilirliği, ne
özneye ne nesneye ait bir özelliktir; ikisi arasındaki bağdır. Sonraki ders bu bağları
birinci sınıf veri hâline getiren ilişki tabanlı erişim denetimini ele alıyor: nesneler ve
özneler bir çizge oluşturuyor, erişim sorusu da o çizge üzerinde bir ulaşılabilirlik
sorgusuna dönüşüyor.
