Cross Domain Engelini Aşmak

iframe kullanmak zorunda olan neredeyse herkesin karşısına çıkmıştır cross-domain problemi ve bir o kadar da baş ağrıtmıştır ilk seferinde. Aynı şey benim de başıma geldiğinden biliyorum. Her şey gibi bunun da çözümü hatta çözümleri var. Kesin çözüm HTML5 postMessage. Bitti 🙂

Alex Sexton bu sunumunda birden fazla çözüm önerisiyle anlatmış ve bunları artıları ve eksileriyle ortaya koymuş. Oldukça başarılı bir anlatım olmuş.

Bunların bir kısmını denedim ve SharePoint 2010 Intranet ortamında karşılaştığım sonuçları ve nihayi çözümü yazıyorum. Yapılanları tek tek anlatmayacağım, sadece çözümü detaylandıracağım. Diğerlerini Alex Sexton’ın sunumunda daha detaylı bulabilirsiniz.

Güvenlik nedenlerinden dolayı iletişimde olacak frame‘lerin protokolleri (http, https), port numaraları (http için 80), ve host‘ları aynı olmalıdır. Aksi takdirde aşağıdaki örnekteki uyarıyla karşılaşırsınız.

Örnek şu: A domainin içindeki B domain’li bir iframe içinden bir input‘ın değerini almak ya da iframe’in içindeki bir elemana değer atamak.
Bunu denediğiniz zaman karşılaşacağınız olası uyarı mesajı şu olacaktır (jQuery mesajı):
Unsafe JavaScript attempt to access frame with URL B from frame with URL A. Domains, protocols and ports must match.

Çözüm Denemeleri:

1- window.name

Buna erişmeyi denediğimde yine aynı uyarıyı aldım.

2- document.domain

İşe yaramadı.

3- iframe içinde en üstteki katmanın domain’inde bir iframe daha açmak

iframe dışındaki domain‘i bilmiyor. URL’ine yazdırılsa bile SharePoint’in bir işlemi sonrasında URL değişiyor. Sadece tek seferinde URL alınabiliyor. Alt katmanda yine işe yaramıyor.

4- window.postMessage

Parmaklar yukarı. Aynı zamanda uygulaması en kolay çözümlerden biri. Olay temelde şu: Bir “event listener” ekliyorsunuz. O mesajın gelmesini tetikte bekliyor. Mesaj bir frame’den diğerine gönderildiği anda onu yakalıyor.

var otherWindow = document.getElementsByTagName('iframe')[0].contentWindow,
    targetDomain = 'http://garage.codersgrave.com',
    sourceDomain = 'http://codersgrave.com';

/*
 * Eğer iframe içinden dışarıya gönderilecekse
 * otherWindow = parent olmalı
 */

// Mesajın gönderileceği ekrandaki kod
otherWindow.postMessage('hoop robocop', targetDomain);


// Mesajın alınacağı ekrandaki kod
if (window.addEventListener) {
  window.addEventListener('message', receiveMessage, false);

// IE8+
} else if (window.attachEvent) {
  window.attachEvent('onmessage', receiveMessage);
}

function receiveMessage (e) {

  // Mesaj beklediğiniz adresten gelmiş ise
  if (e.origin === sourceDomain) {
    alert(e.data);
  }
}

Tarayıcı desteği: Bu örnek IE8-9, Chrome ve Firefox’da test edildi. postMessage desteklemeyen tarayıcılar için Ben Alman’ın çok güzel bir jQuery plugin‘in var. postMessage’a polling, delay ve birkaç kontrol daha eklemiş. IE6-8 ve Opera 9 desteği de veriyor.

Yararlı Kaynaklar

Siz hangi metodu kullanıyorsunuz? Bu yöntem işinize yaradı mı? Yazmaktan çekinmeyin.

  • mehmet alp

    bir ara beni baya uğraştırmış ve çözüm bulamamıştım buna. Postmessage iyiymiş. sormak istediğim :
    jquery le neden yapmıyoruz aşağıda ki kod çalışmaz mı?
    $(“iframe body”).html(‘dasd’);

    ayrıca bir çözümü de burda var :

    http://www.yazilimakademi.com/makale_detay.aspx?id=99&title=IFrame%20i%C3%A7indeki%20elemanlara%20eri%C3%BEim

    teşekkürler yazı için 🙂

    • Selam Mehmet,

      jQuery ile yapmamanın birkaç sebebi var. Birincisi; uygulamada jQuery kullanılmamış olabilir ve sadece postMessage için jQuery yüklemenin anlamı yok. O yüzden sade javascript ile yazdım.

      Yazdığın jQuery kodu da ancak domain’lerin aynı olması durumunda çalışır, verdiğin bağlantıdaki örnek de keza aynı şekilde. İkisi de cross-domain’e takılır.

      İlla jQuery kullanmak istiyorsan yazının sonuna eklediğim jQuery plugin’ini deneyebilirsin. Başarılı oldukça.

  • Hakan

    Merhaba; acaba bu crossdomain.xml dosyaları içinde geçerlimidir, ben akamai sunucularında ki bir yayını jwplayer ile oynatamıyorum crossdomain.xml uyarısı çıkıyor fakat vlc player ile sorunsuz izleniyor.