web-dev-qa-db-fra.com

Erreur: autorisation refusée d'accéder à la propriété "document"

J'ai un document HTML qui contient un iframe. Chaque fois que j'essaie d'accéder ou de modifier ce iframe avec JS, je reçois Error: Permission denied to access property "document".

J'utilise frame.contentWindow.document.body.innerHTML ou frame.contentWindow.document.body.onload ou des attributs similaires pour accéder ou modifier le iframe. (Dans le code donné, iframe est appelé frame.)

Pour l'application Web que je développe, l'accès à ces attributs est nécessaire et je ne peux pas me passer de ceux-ci (ou d'alternatives similaires).

21
sbrm1

Vous pouvez toujours contourner ce problème à l'aide de YQL même si vous n'avez pas accès à la partie en-tête de la fenêtre de réception. Avec la méthode Postmessage, vous devez également modifier le script de la fenêtre du destinataire. Mais en utilisant cette méthode, vous pouvez charger n’importe quel iframe sans toucher à leurs scripts. Regarde ça!

<html>
<iframe src="https://google.com/" width="500" height="300"></iframe>

<script>
var iframe = document.getElementsByTagName('iframe')[0];
var url = iframe.src;
var getData = function (data) {
    if (data && data.query && data.query.results && data.query.results.resources && data.query.results.resources.content && data.query.results.resources.status == 200) loadHTML(data.query.results.resources.content);
    else if (data && data.error && data.error.description) loadHTML(data.error.description);
    else loadHTML('Error: Cannot load ' + url);
};
var loadURL = function (src) {
    url = src;
    var script = document.createElement('script');
    script.src = 'https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20data.headers%20where%20url%3D%22' + encodeURIComponent(url) + '%22&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=getData';
    document.body.appendChild(script);
};
var loadHTML = function (html) {
    iframe.src = 'about:blank';
    iframe.contentWindow.document.open();
    iframe.contentWindow.document.write(html.replace(/<head>/i, '<head><base href="' + url + '"><scr' + 'ipt>document.addEventListener("click", function(e) { if(e.target && e.target.nodeName == "A") { e.preventDefault(); parent.loadURL(e.target.href); } });</scr' + 'ipt>'));
    iframe.contentWindow.document.close();
}

loadURL(iframe.src);
</script>
</html>
8
Gihan Gamage

Accéder à, puis modifier des pages Web dans iframes d’autres sites Web est appelé script intersite ou XSS et c'est une technique utilisée par des pirates informatiques malveillants pour s'en prendre à des victimes sans méfiance.

Une stratégie portant le nom de "Stratégie d'origine identique" est mise en œuvre par les fabricants de navigateur pour empêcher un tel comportement et l'exécution arbitraire de code JS.

Cette erreur peut être évitée en hébergeant le document parent et le document dans iframe dans le même domaine et sous-domaine et en s'assurant que les documents sont chargés à l'aide du même protocole.

Exemples de pages incompatibles:

  1. http://www.example.org & http://www.example2.com
  2. http://abc.example.org & http://xyz.example.com
  3. http://www.example.org & https://www.example.com

Partage de ressources d'origine croisée est une solution à ce problème.

Par exemple:
Si http://www.example.com aimerait partager http://www.example.com/hello avec http://www.example.org, un en-tête peut être envoyé avec le document qui se présente comme suit:

Access-Control-Allow-Origin: http://www.example.org

Pour l'envoyer avec HTML, il suffit de le mettre dans un <META HTTP-EQUIV="..."> tag, comme ceci:

<head>
    ...
    <META HTTP-EQUIV="Access-Control-Allow-Origin" CONTENT="http://www.example.org">
    ...
</head>
20
sbrm1

Vous pouvez utiliser postMessage

Fenêtre 1 - réception

window.addEventListener("message", receiveMessage, false);

function receiveMessage(event)
{
  var Origin = event.Origin || event.originalEvent.Origin; 
  // For Chrome, the Origin property is in the event.originalEvent object.
  if (Origin !== "http://example.org:8080")
    return;

  // ...
}

Fenêtre - 2 Transmission

var popup = window.open(...popup details...);
popup.postMessage(
       "The user is 'bob' and the password is 'secret'", 
       "https://secure.example.net"
);

Vous devez créer une autre paire pour communiquer.

9
joyBlanks