---
title: 'Kaynaklar Arası Paylaşım'
source: 'https://academia.sh/tr/kurslar/frontend-kalitesi/kaynaklar-arasi-paylasim'
course: 'Frontend Kalitesi'
language: tr
updated: '2026-08-17T18:09:22+00:00'
license: 'CC BY-SA 4.0'
---

# Kaynaklar Arası Paylaşım

Aynı kaynak politikasının neyi engellediği, basit istek ile ön denetim ayrımı, paylaşım başlıklarının anlamı, kimlik bilgili isteklerin kuralları ve sık görülen yanlış yapılandırmalar.

Önceki ders, içerik güvenlik politikasının hangi kaynaktan betik yüklenebileceğini
belirlediğini kurdu. Betik yüklendikten sonra ayrı bir sınır devreye girer. Kuzey Yamaç
Ölçüm İstasyonu arayüzü `https://olcum.ornek.test` adresinden sunuluyor, ölçüm verisi ise
ayrı bir alan adındaki bir uçtan geliyor. Arayüzün betiği bu uca istek attığında yanıtı
okuyup okuyamayacağına politika değil, aynı kaynak politikası karar verir.

Bu ders o kararı ve kararı gevşetmenin denetimli yolunu kurar.

## Aynı Kaynak Politikası Neyi Engeller

Tarayıcı ve Web Platformu kursunda tanımlandığı gibi bir **kaynak (origin)** şema, ana
bilgisayar adı ve bağlantı noktasının oluşturduğu üçlüdür. Üçlünün herhangi bir bileşeni
farklıysa kaynak farklıdır: `https://olcum.ornek.test` ile `https://veri.ornek.test` ayrı
kaynaklardır, `http://olcum.ornek.test` de ayrıdır.

Aynı kaynak politikasının ne yaptığı konusundaki en sık yanılgı, isteğin gönderilmesini
engellediği sanısıdır. Engellenen şey **yanıtın okunmasıdır**. Betik başka bir kaynağa
istek gönderebilir, istek sunucuya ulaşır, sunucu isteği işler ve yanıt verir; tarayıcı
yanıtı betiğe teslim etmez. İstek yan etki üretmişse o yan etki gerçekleşmiştir.

Bu ayrım sonraki dersin konusunu doğurur ve burada not edilmelidir: politika okumayı
kısıtlar, yazmayı değil.

Politika yalnız betikten açılan bağlantılar için geçerlidir. Görsel, biçem dosyası, yazı
tipi ve betik ögeleri başka kaynaklardan yükleme yapabilir; belge bunları gömer ama
içeriklerini okuyamaz. Tarayıcı ve Web Platformu kursundaki Servis Çalışanları dersinde
tanıtılan **saydam yanıt** kavramı bu durumun adıdır: yanıt kullanılabilir, ama gövdesi ve
başlıkları program tarafından görülemez.

## Basit İstek ve Ön Denetim

Kaynaklar arası isteklerin bir bölümü doğrudan gönderilir, bir bölümü gönderilmeden önce
izin sorar.

Doğrudan gönderilen istekler, formların uzun süredir kaynaklar arası yapabildiği
isteklerdir: `GET`, `HEAD` veya `POST` yöntemi, sınırlı bir içerik türü kümesi ve
uygulamanın eklemediği başlıklar. Bu istekler için ek bir tur yoktur; tarayıcı isteği
gönderir ve yanıtın okunup okunamayacağına dönen başlıklara bakarak karar verir.

Bunun dışındaki her istek **ön denetim (preflight)** gerektirir. Yöntem `PUT` veya `DELETE`
ise, içerik türü `application/json` ise, uygulama `X-` ile başlayan bir başlık ekliyorsa
tarayıcı önce `OPTIONS` yöntemiyle ayrı bir istek gönderir. Bu istekte
`Access-Control-Request-Method` ve `Access-Control-Request-Headers` başlıkları, asıl
isteğin ne yapacağını sunucuya bildirir. Sunucu izin verirse asıl istek gönderilir;
vermezse asıl istek hiç oluşmaz.

Ön denetimin varlık nedeni geriye dönük uyumluluktur. Tarayıcının doğrudan
gönderebileceği istekler zaten formlarla gönderilebilen isteklerdir; yeni yetenekler
sunucunun haberi olmadan kullanıma açılmaz.

## Sunucu Tarafındaki Yapılandırma

Aşağıdaki sunucu ölçüm verisini sunar ve paylaşım kararını tek bir izin listesi üzerinden
verir.

```js
// cors-sunucu.mjs — olcum ucunun kaynaklar arasi paylasim yapilandirmasi
import { createServer } from 'node:http';

const IZINLI_KAYNAKLAR = new Set(['https://olcum.ornek.test']);
const IZINLI_YONTEMLER = 'GET, POST, OPTIONS';
const IZINLI_BASLIKLAR = 'content-type, x-olcum-anahtari';

const sunucu = createServer((istek, yanit) => {
  const kaynak = istek.headers.origin;
  const izinli = kaynak !== undefined && IZINLI_KAYNAKLAR.has(kaynak);

  yanit.setHeader('Vary', 'Origin');
  if (izinli) {
    yanit.setHeader('Access-Control-Allow-Origin', kaynak);
    yanit.setHeader('Access-Control-Allow-Credentials', 'true');
  }

  if (istek.method === 'OPTIONS') {
    if (izinli) {
      yanit.setHeader('Access-Control-Allow-Methods', IZINLI_YONTEMLER);
      yanit.setHeader('Access-Control-Allow-Headers', IZINLI_BASLIKLAR);
      yanit.setHeader('Access-Control-Max-Age', '600');
    }
    yanit.writeHead(204).end();
    return;
  }

  yanit.setHeader('Content-Type', 'application/json');
  yanit.end(JSON.stringify({ istasyon: 'kuzey-yamac', sicaklik: -3.4 }));
});

sunucu.listen(8791, '127.0.0.1', () => {
  console.log('dinliyor: http://127.0.0.1:8791');
});
```

Sunucu arka planda başlatılır, üç istek gönderilir ve sonunda durdurulur. Bayrak
`-D -` yanıt başlıklarını standart çıktıya yazar; `tr -d '\r'` satır sonlarındaki taşıma
karakterini ayıklar, `grep` ise her çalıştırmada değişecek olan tarih satırını eler.

```bash
node cors-sunucu.mjs &
sunucu=$!
sleep 1

echo '--- 1. izinli kaynaktan on denetim ---'
curl -s -o /dev/null -D - -X OPTIONS http://127.0.0.1:8791/olcum \
  -H 'Origin: https://olcum.ornek.test' \
  -H 'Access-Control-Request-Method: POST' \
  -H 'Access-Control-Request-Headers: content-type' | tr -d '\r' | grep -v '^Date:'

echo '--- 2. listede olmayan kaynaktan on denetim ---'
curl -s -o /dev/null -D - -X OPTIONS http://127.0.0.1:8791/olcum \
  -H 'Origin: https://baska.ornek.test' \
  -H 'Access-Control-Request-Method: POST' \
  -H 'Access-Control-Request-Headers: content-type' | tr -d '\r' | grep -v '^Date:'

echo '--- 3. izinli kaynaktan gercek istek ---'
curl -s -D - http://127.0.0.1:8791/olcum \
  -H 'Origin: https://olcum.ornek.test' | tr -d '\r' | grep -v '^Date:'

kill $sunucu
```

```
dinliyor: http://127.0.0.1:8791
--- 1. izinli kaynaktan on denetim ---
HTTP/1.1 204 No Content
Vary: Origin
Access-Control-Allow-Origin: https://olcum.ornek.test
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: content-type, x-olcum-anahtari
Access-Control-Max-Age: 600
Connection: keep-alive
Keep-Alive: timeout=5

--- 2. listede olmayan kaynaktan on denetim ---
HTTP/1.1 204 No Content
Vary: Origin
Connection: keep-alive
Keep-Alive: timeout=5

--- 3. izinli kaynaktan gercek istek ---
HTTP/1.1 200 OK
Vary: Origin
Access-Control-Allow-Origin: https://olcum.ornek.test
Access-Control-Allow-Credentials: true
Content-Type: application/json
Connection: keep-alive
Keep-Alive: timeout=5
Content-Length: 42

{"istasyon":"kuzey-yamac","sicaklik":-3.4}
```

İkinci durum, reddin nasıl göründüğünü gösterir. Sunucu bir hata kodu döndürmez; yalnızca
izin başlıklarını yazmaz. Karar tarayıcıya aittir ve tarayıcı, izin başlığı bulunmayan bir
ön denetimden sonra asıl isteği hiç göndermez. Bu, ret durumunun neden sunucu günlüğünde
bir hata olarak görünmediğini de açıklar.

## Başlıkların Anlamı

`Access-Control-Allow-Origin`, yanıtı okumasına izin verilen tek kaynağı bildirir. Değeri
ya tam bir kaynak dizgisidir ya da tüm kaynakları gösteren yıldızdır.

`Access-Control-Allow-Methods` ve `Access-Control-Allow-Headers` yalnız ön denetim
yanıtında anlamlıdır; asıl isteğin hangi yöntemi ve hangi başlıkları kullanabileceğini
sayar. `Access-Control-Max-Age`, ön denetim sonucunun kaç saniye önbelleğe alınabileceğini
söyler; her istekten önce bir tur daha atılmasını engeller.

`Access-Control-Expose-Headers`, betiğin yanıt üzerinde hangi başlıkları okuyabileceğini
genişletir. Öntanımlı olarak yalnızca küçük bir başlık kümesi okunabilir; sayfalama
bilgisini özel bir başlıkta taşıyan bir uç, o başlığı burada saymazsa betik başlığı
göremez.

`Vary: Origin` bir izin başlığı değildir ama eksikliği gerçek bir kusurdur. Yanıtın içeriği
istekteki `Origin` başlığına göre değiştiği için, aradaki her önbellek bu başlığı önbellek
anahtarına katmalıdır. Katmazsa, izinli bir kaynak için üretilmiş izin başlıkları başka bir
kaynağa sunulabilir.

## Kimlik Bilgili İstekler

Çerezlerin ve kimlik başlıklarının kaynaklar arası isteğe eklenmesi ayrıca istenmelidir.
İstemci tarafında bu, isteğin kimlik bilgisi taşıyacağının belirtilmesiyle olur; sunucu
tarafında iki kural birden geçerlidir.

Birincisi, `Access-Control-Allow-Credentials` başlığı `true` değerini taşımalıdır.
İkincisi, `Access-Control-Allow-Origin` yıldız olamaz; tam kaynak dizgisi yazılmalıdır.
Bu kural, "herkese açık" bir yapılandırmanın yanlışlıkla kimlik bilgisi taşıyan istekleri
kapsamasını engeller.

Çerezin gerçekten gönderilmesi ayrı bir koşula daha bağlıdır: çerezin `SameSite` niteliği
kaynaklar arası gönderime izin vermelidir. Bu nitelik sonraki dersin konusudur ve iki
mekanizma birlikte değerlendirilmelidir; paylaşım başlıkları doğru olsa bile çerez
niteliği engelliyorsa istek kimliksiz gider.

## Sık Görülen Yanlış Yapılandırmalar

**Gelen kaynağı olduğu gibi yansıtmak.** İstekteki `Origin` başlığını doğrulamadan yanıta
yazan bir sunucu, izin listesi tutuyor gibi görünür ama her kaynağa izin vermiş olur.
Yukarıdaki örnekte yansıtma yapılıyor, ancak yalnız listede bulunan bir değer için.

**Yıldızı kimlik bilgisiyle birlikte kullanmaya çalışmak.** Tarayıcı bunu reddeder; bu
reddi aşmak için kaynağı yansıtmaya geçmek, ilk kusuru üretir.

**Alan adı eşleşmesini gevşek yazmak.** `ornek.test` ile biten her adı kabul eden bir
denetim, `ornek.test.baska.test` adını da kabul eder. Eşleşme dizgi sonu üzerinden değil,
tam kaynak karşılaştırmasıyla yapılır.

**`null` kaynağına izin vermek.** Bazı bağlamlar `Origin` başlığını `null` olarak gönderir;
bu değeri izin listesine koymak, o bağlamların hepsine izin vermek demektir.

## Paylaşım Bir Yetkilendirme Değildir

Kaynaklar arası paylaşım, kullanıcının tarayıcısını başka bir sitenin betiğinin veri
okumasına karşı korur. Sunucuyu korumaz. Tarayıcı olmayan bir istemci bu başlıkları hiç
dikkate almaz; izin listesinde bulunmayan bir kaynak adı yazmak da bir engel oluşturmaz,
çünkü `Origin` başlığını tarayıcı dışında hiçbir şey zorunlu kılmaz.

Bundan çıkan kural nettir: bir uç, kimlik doğrulaması ve yetkilendirmesi olmadan
korunmuş sayılmaz. Paylaşım yapılandırması bu denetimlerin yerine geçmez, üzerine eklenir.

## Özet

- Aynı kaynak politikası kaynaklar arası isteğin gönderilmesini değil, yanıtının
  okunmasını engeller; yan etki üreten bir istek yine de gerçekleşir.
- Basit koşulları sağlamayan istekler `OPTIONS` yöntemiyle bir ön denetim turu geçirir;
  sunucu izin vermezse asıl istek hiç oluşmaz.
- Ret, hata kodu olarak değil, izin başlıklarının yokluğu olarak görünür.
- Kimlik bilgili isteklerde `Access-Control-Allow-Origin` yıldız olamaz ve
  `Access-Control-Allow-Credentials` gerekir; çerezin `SameSite` niteliği ayrıca izin
  vermelidir.
- Paylaşım yapılandırması tarayıcı içindir; sunucunun kimlik doğrulaması ve
  yetkilendirmesi bundan bağımsız olarak gereklidir.

## Sonraki Adım

Bu dersin başındaki ayrım açık bir soru bıraktı: aynı kaynak politikası okumayı engelliyorsa
ve yazma isteği yine de sunucuya ulaşıyorsa, başka bir sitenin sayfası kullanıcının oturumu
üzerinden bir ölçüm kaydı silebilir mi? Yanıtın okunamaması, işlemin yapılmadığı anlamına
gelmez. Sonraki ders bu saldırı sınıfını, çerez niteliklerinin ve istek belirteçlerinin
oluşturduğu savunmayı ele alır.
