English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Analisi e soluzioni per la trasmissione a dominio incrociato di JavaScript

Cos'è il cross-domain

Per motivi di sicurezza, JavaScript non permette chiamate cross-domain ad altri oggetti delle pagine, ma allo stesso tempo, le limitazioni di sicurezza hanno portato non poche difficoltà all'inserimento di iframe o applicazioni ajax. Ecco una semplice raccolta di problemi relativi al cross-domain:

Prima di tutto, cosa significa cross-domain, in modo semplice si può capire che è perché la politica di origine di JavaScript limita, i js sotto il dominio a.com non possono operare sugli oggetti del dominio b.com o c.a.com. Una spiegazione più dettagliata può essere trovata nel seguente elenco:

URL Spiegazione Consentire o meno la comunicazione
http://www.a.com/a.js
http://www.a.com/b.js
Nello stesso dominio È permesso
http://www.a.com/lab/a.js
http://www.a.com/script/b.js
Diversi cartelli nello stesso dominio È permesso
http://www.a.com:8000/a.js
http://www.a.com/b.js
Stesso dominio, diversi porti Non è permesso
http://www.a.com/a.js
https://www.a.com/b.js
Stesso dominio, diversi protocolli Non è permesso
http://www.a.com/a.js
http://70.32.92.74/b.js
Corrispondenza tra dominio e IP del dominio Non è permesso
http://www.a.com/a.js
http://script.a.com/b.js
Dominio principale lo stesso, sottodominio diverso Non è permesso
http://www.a.com/a.js
http://a.com/b.js
Stesso dominio, diversi sottodomini (come sopra) Non è permesso (in questo caso non è permesso accedere anche ai cookie)
http://www.cnblogs.com/a.js
http://www.a.com/b.js
Domini diversi Non è permesso

Attenzione a due punti:

Primo, se il problema di cross-domain è causato dal protocollo e dal porto, il "front-end" è impotente.

Secondo: nel problema di cross-domain, il dominio è identificato solo attraverso l'header dell'URL e non tenta di determinare se lo stesso indirizzo IP corrisponde a due domini o se due domini si trovano sullo stesso IP.

L'header dell'URL si riferisce a window.location.protocol + window.location.host, può anche essere inteso come "Domains, protocols and ports must match".

接下来简单地总结一下在“前台”一般处理跨域的方法,后台proxy这种方案涉及到后台配置,这里就不阐述了。

1、document.domain+iframe的设置
对于主域相同而子域不同的例子,可以通过设置document.domain的方法来解决。具体做法是可以在http://www.a.com/a.htmlhttp://script.a.com/b.html在两个文件中分别加上 document.domain = 'a.com';然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以“交互”了。当然这种办法只能解决主域相同而二级域名不同的情况,如果你异想天开地把script.a.com的domain设为alibaba.com,那显然是会报错的!代码如下:

www.a.com上的a.html

document.domain = 'a.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.a.com/b.html';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
  var doc = ifr.contentDocument || ifr.contentWindow.document;
  // 在这里操纵b.html
  alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
});

script.a.com上的b.html

document.domain = 'a.com';

这种方式适用于{www.kuqin.com, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何页面相互通信。

备注:某一页面的domain默认等于window.location.hostname。主域名是不带www的域名,例如a.com,主域名前面带前缀的通常都是二级域名或多级域名,例如www.a.com实际上是二级域名。domain只能设置为主域名,不可以在b.a.com中将domain设置为c.a.com。

问题:

1、安全性,当一个站点(b.a.com)被攻击后,另一个站点(c.a.com)会引起安全漏洞。

2、如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同的domain。

2. Creare script dinamicamente

Nonostante i browser bloccano di default l'accesso cross-domain, non bloccano l'uso di script di altri domini all'interno della pagina e possono eseguire liberamente le funzioni dei file JS introdotti (inclusi l'operazione dei cookie, Dom, ecc.). Sulla base di questo, e' possibile trasmettere dati cross-domain creando nodi script. La pratica puo' essere consultata nel YUI Get Utility

E' interessante giudicare se il nodo script e' stato caricato: ie puo' solo passare attraverso l'attributo readystatechange del script, altri browser sono l'evento load del script. Ecco alcuni metodi per giudicare se il script e' stato caricato.

js.onload = js.onreadystatechange = function() {
  if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
    // callback qui esegue
    js.onload = js.onreadystatechange = null;
  }
});

3. Utilizzare iframe e location.hash

Questo metodo e' un po' ingegnoso, ma puo' risolvere il problema del sostituzione delle script in situazioni completamente cross-domain. Il principio e' utilizzare location.hash per trasmettere valori. Nella url: http://a.com#hellowordL'hash '#helloworld' rappresenta location.hash, modificare l'hash non causera' un refresh della pagina, quindi puo' essere utilizzato per trasmettere dati, ovviamente la capacita' di dati e' limitata. Supponiamo che il file cs1.html sotto il dominio a.com debba trasmettere informazioni al cs2.html del dominio cnblogs.com, cs1.html deve prima creare un iframe nascosto, il src dell'iframe punta alla pagina cs2.html del dominio cnblogs.com, in questo momento l'hash puo' essere utilizzato come parametro di trasmissione. Dopo che cs2.html ha risposto alla richiesta, i dati saranno trasmessi modificando l'hash di cs1.html (poiche' due pagine non sono nello stesso dominio, IE e Chrome non permettono di modificare il valore di parent.location.hash, quindi e' necessario utilizzare un iframe proxy sotto il dominio a.com; Firefox puo' farlo). Allo stesso tempo, aggiungere un timer a cs1.html per controllare periodicamente se il valore di location.hash e' cambiato, se e' cambiato, ottenere il valore dell'hash. Il codice e' il seguente:

Prima del file cs1.html sotto a.com: }}

function startRequest(){
  var ifr = document.createElement('iframe');
  ifr.style.display = 'none';
  ifr.src = 'http://www.cnblogs.com/lab/cscript/cs2.html#paramdo';
  document.body.appendChild(ifr);
}
function checkHash() {
  try {
    var data = location.hash ? location.hash.substring(1) : '';
    if (console.log) {
      console.log('Ora i dati sono '+data);
    }
  }
}
setInterval(checkHash, 2000);

cs2.html sotto il dominio cnblogs.com:

//Simulazione di un'operazione di elaborazione dei parametri semplice
switch(location.hash){
  case '#paramdo':
    callBack();
    break;
  case '#paramset':
    //fare qualcosa……
    break;
}
function callBack(){
  try {
    parent.location.hash = 'somedata';
  }
    // Il meccanismo di sicurezza di ie e chrome non consente di modificare parent.location.hash
    // Pertanto, si deve utilizzare un iframe di proxy sotto il dominio cnblogs
    var ifrproxy = document.createElement('iframe');
    ifrproxy.style.display = 'none';
    ifrproxy.src = 'http://a.com/test/cscript/cs3.html#somedata';  // Attenzione: il file si trova nel dominio "a.com"
    document.body.appendChild(ifrproxy);
  }
}

Il dominio cs3.html sotto a.com

// Poiché parent.parent e se stesso appartengono allo stesso dominio, è possibile modificare il valore di location.hash
parent.parent.location.hash = self.location.hash.substring(1);

Naturalmente, fare così ha molti svantaggi, come l'esposizione diretta dei dati nell'URL, la capacità e il tipo dei dati sono limitati ecc ...

4, Trasmissione dei dati cross-domain tramite window.name

Ci sono tre pagine:

  1. a.com/app.html: La pagina dell'applicazione.
  2. a.com/proxy.html: Il file proxy, generalmente un file html senza contenuto, deve essere nello stesso dominio della pagina dell'applicazione.
  3. b.com/data.html: La pagina che l'applicazione deve ottenere i dati, può essere chiamata pagina dei dati.

I passaggi fondamentali per l'implementazione sono i seguenti:

1、Nella pagina dell'applicazione (a.com/app.html) creare un iframe, impostare la proprietà src verso la pagina dei dati (b.com/data.html).
La pagina dei dati aggiungerà i dati alla proprietà window.name di questo iframe, ecco il codice di data.html:

<script type="text/javascript">
  window.name = 'I was there!';  // Questi sono i dati da trasmettere, la dimensione è generalmente di 2M, sotto IE e firefox può essere fino a circa 32M
                   // Il formato dei dati può essere personalizzato, come json, stringa
</script>

2、Nella pagina dell'applicazione (a.com/app.html) ascoltare l'evento onload dell'iframe, in questo evento impostare la proprietà src di questo iframe verso il file proxy del dominio locale (il file proxy e la pagina dell'applicazione sono nello stesso dominio, quindi possono comunicare tra loro). Ecco una parte del codice di app.html:

<script type="text/javascript">
  var state = 0; 
  iframe = document.createElement('iframe'),
  loadfn = function() {
    if (state === 1) {
      var data = iframe.contentWindow.name;  // Lettura dei dati
      alert(data);  // Visualizza 'I was there!'
    } else if (state === 0) {
      state = 1;
      iframe.contentWindow.location = "http://a.com/proxy.html";  // Impostazione del file proxy
    } 
  });
  iframe.src = 'http://b.com/data.html';
  if (iframe.attachEvent) {
    iframe.attachEvent('onload', loadfn);
  } else {
    iframe.onload = loadfn;
  }
  document.body.appendChild(iframe);
</script>

3. Dopo aver ricevuto i dati, distruggi questo iframe per liberare la memoria; questo garantisce anche la sicurezza (non può essere acceduto dal js di altri domini frame).

<script type="text/javascript">
  iframe.contentWindow.document.write('');
  iframe.contentWindow.close();
  document.body.removeChild(iframe);
</script>

5. Utilizzo di HTML5 postMessage

Una delle funzionalità più interessanti di HTML5 è il Cross Document Messaging. Tutti i browser di nuova generazione supporteranno questa funzione: Chrome 2.0+, Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, e Safari 4.0+. Facebook ha già utilizzato questa funzione, supportando la trasmissione di messaggi in tempo reale basata su web tramite postMessage.

otherWindow.postMessage(message, targetOrigin);

otherWindow: riferimento alla pagina che riceve le informazioni, window. Può essere l'attributo contentWindow di un iframe; il valore di ritorno di window.open; il valore ottenuto tramite name o indice da window.frames.

message: i dati da inviare, tipo stringa.

targetOrigin: utilizzato per limitare otherWindow, "*" significa senza limiti

Codice in a.com/index.html:

<iframe id="ifr" src="b.com/index.html"></iframe>
<script type="text/javascript">
window.onload = function() {
  var ifr = document.getElementById('ifr');
  var targetOrigin = 'http://b.com'; // Se scritto come 'http://b.com/c/proxy.html', avrà lo stesso effetto
                    // Se scritto come 'http://c.com', non verrà eseguito postMessage
  ifr.contentWindow.postMessage('I was there!', targetOrigin);
});
</script>

Codice nella pagina index.html di b.com:

<script type="text/javascript">
  window.addEventListener('message', function(event){
    // Giudizio dell'indirizzo di origine del messaggio tramite proprietà origin
    if (event.origin == 'http://a.com') {
      alert(event.data);  // Visualizza "I was there!"
      alert(event.source); // Riferimento all'oggetto window in a.com/index.html
                 // Ma a causa della strategia di origine, non è possibile accedere all'oggetto window con event.source
    }
  }, false);

6. Utilizzando flash
Questo è il metodo visto nel componente IO di YUI3.
Puoi vedere ulteriori specifiche di policy di proxy di dominio incrociato e blacklist di header HTTP su Adobe Developer Connection:ross-Domain Policy File Specifications, HTTP Headers Blacklist.

Questo è tutto il contenuto dell'articolo, spero che sia utile per la tua apprendimento e spero che tu supporti fortemente la guida Yell.

Dichiarazione: il contenuto di questo articolo è stato prelevato da Internet, il copyright è di proprietà del rispettivo autore, il contenuto è stato contribuito e caricato autonomamente dagli utenti di Internet, questo sito non detiene i diritti di proprietà, non è stato editato manualmente e non assume responsabilità legali correlate. Se trovi contenuti sospetti di violazione del copyright, è possibile inviare una e-mail a: notice#oldtoolbag.com (al momento dell'invio dell'e-mail, sostituisci # con @) per segnalare il problema e fornire prove pertinenti. Una volta verificata, questo sito eliminerà immediatamente i contenuti sospetti di violazione del copyright.

Ti potrebbe interessare