- Konu sahibi
- #1
CORS, bir sayfanın başka bir origin üzerindeki HTTP yanıtını JavaScript ile okuyup okuyamayacağını belirler.
İki adresin aynı origin sayılması için protokol, alan adı ve portun üçü de aynı olmalıdır. Örneğin aşağıdaki adresler farklı origin'dir:
Yalnızca yolun değişmesi origin'i değiştirmez.
Farklı origin'deki iframe'in yüklenmesine genellikle izin verilebilir; fakat tarayıcı üst sayfanın belge içeriğini okumasını Same-Origin Policy ile sınırlar. CORS burada iframe DOM erişimi için değil, örneğin üst sayfadaki
Bu kurgusal örnek, iki adresi de kontrol edebildiğiniz normal HTTP origin’leri varsayar. Üst sayfanız
Farklı origin durumunda
İhtiyacınız yalnızca iframe içeriğini göstermekse CORS ayarlamayın. İhtiyacınız üst sayfa ile iframe arasında veri alışverişiyse
Önceki DOM kontrolü örneğiyle aynı değişkeni ikinci kez tanımlamayın; mesajlaşma denemesinde o script yerine yukarıdaki üst-sayfa kodunu kullanın. Aşağıdaki kod ise
Örnekte yalnız
Aşağıdaki ayrım, yanlış HTTP başlığı eklemenizi önler.
Üst sayfanın CSP
Normal bir origin altında çalışan iframe kendi origin’indeki API’yi çağırıyorsa CORS izni gerekmez. Üst sayfanın origin’i bu isteğin kaynağı sayılmaz. Ancak sandbox ile opaque origin oluşmuşsa veya başka tarayıcı politikaları varsa davranış farklılaşabilir.
Sandbox,
iframe ise başka bir belgeyi sayfaya gömmek için kullanılır. Bu nedenle CORS başlığı eklemek, üst sayfanın iframe içindeki DOM'a erişmesini sağlamaz. Iframe görüntülenebilir; ancak iframe farklı origin üzerindeyse üst sayfa contentDocument, document.body veya iframe içindeki değişkenleri okuyamaz.Önce origin farkını belirleyin
İki adresin aynı origin sayılması için protokol, alan adı ve portun üçü de aynı olmalıdır. Örneğin aşağıdaki adresler farklı origin'dir:
Kod:
https://example.com
https://www.example.com
http://example.com
https://example.com:8443
Yalnızca yolun değişmesi origin'i değiştirmez.
https://example.com/a ile https://example.com/b aynı origin'dir.Farklı origin'deki iframe'in yüklenmesine genellikle izin verilebilir; fakat tarayıcı üst sayfanın belge içeriğini okumasını Same-Origin Policy ile sınırlar. CORS burada iframe DOM erişimi için değil, örneğin üst sayfadaki
fetch() veya XMLHttpRequest çağrısının uzak sunucudan gelen yanıtı okuyabilmesi için kullanılır.Somut örnek: iframe açılıyor ama DOM okunamıyor
Bu kurgusal örnek, iki adresi de kontrol edebildiğiniz normal HTTP origin’leri varsayar. Üst sayfanız
https://example.com, iframe https://www.example.com/frame.html üzerinde olsun. Karşı tarafın katılımı olmadan herhangi bir uzak siteye mesajlaşma özelliği eklenemez:
Kod:
<iframe id="frame" title="Örnek alt sayfa" src="https://www.example.com/frame.html"></iframe>
<script>
const frame = document.getElementById("frame");
frame.addEventListener("load", () => {
const doc = frame.contentDocument;
if (doc === null) {
console.log("Bu belge üst sayfaya same-origin erişimi vermiyor.");
return;
}
console.log(doc.body.textContent);
});
</script>
Farklı origin durumunda
contentDocument null döner; örnek bunu kontrol edip içeriği okumaz. Doğrudan contentWindow.document erişimi ise güvenlik hatası oluşturabilir. Uzak sunucuya Access-Control-Allow-Origin eklemek de bu sonucu değiştirmez; çünkü CORS, iframe belgesinin DOM yetkisini genişleten bir mekanizma değildir.İhtiyacınız yalnızca iframe içeriğini göstermekse CORS ayarlamayın. İhtiyacınız üst sayfa ile iframe arasında veri alışverişiyse
window.postMessage() kullanın:
Kod:
const frame = document.getElementById("frame");
const expectedOrigin = "https://www.example.com";
frame.addEventListener("load", () => {
frame.contentWindow.postMessage(
{ type: "theme", value: "dark" },
expectedOrigin
);
});
window.addEventListener("message", (event) => {
if (event.origin !== expectedOrigin) return;
if (event.source !== frame.contentWindow) return;
const data = event.data;
if (!data || typeof data !== "object") return;
if (data.type !== "theme-received" || data.value !== "dark") return;
console.log("Iframe yanıtı:", data.value);
});
Önceki DOM kontrolü örneğiyle aynı değişkeni ikinci kez tanımlamayın; mesajlaşma denemesinde o script yerine yukarıdaki üst-sayfa kodunu kullanın. Aşağıdaki kod ise
frame.html belgesinde çalışmalıdır:
Kod:
window.addEventListener("message", (event) => {
if (event.origin !== "https://example.com") return;
if (event.source !== window.parent) return;
const data = event.data;
if (!data || typeof data !== "object") return;
if (data.type !== "theme" || data.value !== "dark") return;
document.documentElement.dataset.theme = data.value;
event.source.postMessage(
{ type: "theme-received", value: data.value },
"https://example.com"
);
});
Örnekte yalnız
dark değerine izin verilir; bu bir tema değişkenini işaretler, CSS tasarımı içermez. Burada event.origin doğrulanmalı ve bilinen hedef için * kullanılmamalıdır. Mesaj içeriğini de beklenen biçimde kontrol edin. Başarılı sonuç, DOM'u doğrudan okumak değil, iki pencerenin kontrollü mesajlaşmasıdır.Hangi durumda ne yapmalısınız?
Aşağıdaki ayrım, yanlış HTTP başlığı eklemenizi önler.
| İhtiyaç | Doğru yaklaşım | CORS yeterli mi? |
|---|---|---|
| Uzak sayfayı iframe içinde göstermek | Iframe URL'sini kullanın; gömülme politikalarını kontrol edin | Hayır |
| Üst sayfanın uzak API yanıtını okuması | API sunucusunda uygun CORS yanıtı verin | Evet, API isteği için |
| Iframe ile veri alışverişi | postMessage ve origin doğrulaması kullanın | Hayır |
| Iframe DOM'una doğrudan erişim | Aynı origin ve uygun sandbox politikası gerekir | Hayır |
frame-src politikası da yüklemeyi kısıtlayabilir. Iframe hiç açılmıyorsa sorun CORS yerine X-Frame-Options veya Content Security Policy içindeki frame-ancestors kuralı olabilir. Örneğin X-Frame-Options: DENY tüm iframe gömmelerini engeller; SAMEORIGIN ise yalnızca aynı origin'deki gömmeye izin verir.Uygulanabilir teşhis adımları
- Üst sayfanın ve iframe
srcadresinin protokol, alan adı ve portunu karşılaştırın. - Iframe yalnızca gösterilecekse tarayıcı geliştirici araçlarında yanıtın
X-Frame-OptionsveContent-Security-Policybaşlıklarını kontrol edin. - API çağrısı üst sayfanın JavaScript'i tarafından yapılıyorsa API yanıtında izin verilen origin'in bulunup bulunmadığını kontrol edin.
- Iframe ile mesajlaşacaksanız iki tarafta da
postMessage()kullanın; alıcıdaevent.originve mümkünseevent.sourcedoğrulayın. - Iframe DOM'una erişim zorunluysa iframe ve üst sayfayı aynı protokol, host ve port altında sunun. Sandbox gibi ek kısıtlamalar bulunmadığını da kontrol edin. Aksi durumda CORS eklemek yerine mimariyi mesajlaşmaya göre değiştirin.
Sık sorulan sorular
Iframe içindeki sayfa kendi API’sine CORS olmadan istek atabilir mi?
Normal bir origin altında çalışan iframe kendi origin’indeki API’yi çağırıyorsa CORS izni gerekmez. Üst sayfanın origin’i bu isteğin kaynağı sayılmaz. Ancak sandbox ile opaque origin oluşmuşsa veya başka tarayıcı politikaları varsa davranış farklılaşabilir.
Aynı host üzerindeki sandbox iframe neden DOM erişimi vermeyebilir?
Sandbox,
allow-same-origin olmadan belgeye opaque origin verebilir. Bu durumda URL’ler aynı görünse de DOM erişimi aynı-origin gibi davranmaz. Sırf hatayı gidermek için sandbox izinlerini topluca açmayın; özellikle aynı-origin içerikte script ve same-origin izinlerinin birlikte verilmesi izolasyonu zayıflatabilir.document.domain kullanarak bu sınırı kaldırabilir miyim?
document.domain ile origin gevşetme yaklaşımı kullanım dışına alınmaktadır ve modern güvenlik özellikleriyle uyumsuzluk taşır. Yeni uygulamada belirli origin ve kaynak pencereyi doğrulayan mesajlaşma tercih edin; karşı tarafı kontrol edemiyorsanız onun DOM’una erişim yetkisi elde edemezsiniz.