2017-08-15 3 views
2

Dans la maquette HTML suivante, les cadres iFrench imbriqués proviennent de différents sous-domaines. Cela provoque des messages tels que erreur: Autorisation refusée pour accéder à la propriété « document »Script utilisateur pour contourner la règle d'origine identique pour accéder aux cadres i imbriqués

<html> 
<head> 
    <title></title> 
</head> 
<body> 
    <div> 
     <iframe id="outer_iframe_1" src="https://subdomain1.example.com"></iframe> 
    </div> 
    <div> 
     <iframe id="outer_iframe_2" src="https://subdomain2.example.com"> 
     <div> 
      <iframe id="inner_iframe_2" src="https://subdomain4.example.com"></iframe> 
     </div> 
     </iframe> 
    </div> 
    <div> 
     <iframe id="outer_iframe_3" src="https://subdomain3.example.com"></iframe> 
    </div> 
</body> 
</html> 

Je comptais aller chercher et modifier les valeurs dans les iframes imbriquées avec une UserScript, donc sans passer par le même (par exemple inner_frame_2.) La politique d'origine devrait être possible. Mais des exemples de GM_xmlhttpRequest semblent s'appuyer sur des requêtes GET/POST, alors que je veux seulement traiter les données de page déjà chargées dans ces iframes. Ai-je mal compris GM_xmlhttpRequest, ou y at-il une autre approche que je devrais prendre ici?

+0

Êtes-vous le droit de modifier le contenu (scripts) des iframes? Ou voulez-vous contrôler les sites extraterrestres à distance? –

+0

@ NilsRückmann Je ne suis pas certain de comprendre la question, mais je n'ai aucun contrôle sur le code du site. J'espère que cela pourra aider! –

Répondre

2

Je pense que la seule façon de le faire est d'utiliser la méthode window.postMessage() pour envoyer des messages avec des données de iframes vers la fenêtre supérieure. Pour attraper chaque iframe dans le script Greasemonkey, voir Brock Adams answer sur Apply a Greasemonkey userscript to an iframe?; vous devrez utiliser comme la directive GM @match ceci:

// @match  http://subdomain1.example.com/* 

ou

// @match  *.example.com/* 

Ensuite, vous pouvez vérifier si la fenêtre actuelle est la fenêtre du haut, et/ou vérifier la document.domain pour identifier la iframe:

// ==UserScript== 
// @name   New Userscript 
// @match  http://main-domain.something 
// @match  *.example.com/* 
// ==/UserScript== 

(function() { 
    'use strict'; 

    if (window.top === window.self) { 
     // Here we are at the top window and we setup our message event listener 
    } 
    else { 
     // Here we get inside the iframes. 
     // We can address and check each iframe url with document.domain 
    } 
})(); 

Nous avons besoin de brancher un événement pour "message" à la fenêtre du haut qui traitera chaque message qu'il reçoit des iframes avec les données:

window.addEventListener("message", function(event) { 
    // do something with the event.data 
}, false); 

Et nous pouvons identifier les iframes en utilisant document.domain; faire toutes les manipulations dont nous avons besoin pour les éléments iframe; récupérer toutes les données que nous voulons et envoyer le message à la fenêtre du haut:

window.top.postMessage({ 
    // data object we send to the top window 
}, "*"); 

J'ai créé une démo pour essayer et cela fonctionne assez bien. Mon URL de la fenêtre supérieure est http://zikro.gr/dbg/gm/iframes/main.php et les sous-domaines sont comme http://subdomain1.zikro.gr/. La fenêtre supérieure HTML est identique à la vôtre avec mes iframe urls et le script GM:

// ==UserScript== 
// @name   New Userscript 
// @namespace http://tampermonkey.net/ 
// @version  0.1 
// @description try to take over the world! 
// @author  You 
// @match  http://zikro.gr/dbg/gm/iframes/main.php 
// @match  *.zikro.gr/* 
// @grant  none 
// ==/UserScript== 

(function() { 
    'use strict'; 

    if (window.top === window.self) { 
     // Here we are at the top window and we setup our message event listener 
     document.body.style.backgroundColor = "#f00"; // Just a UI change to identify the top window 
     window.addEventListener("message", function(event) { 
      window.console.log("This is data from '" + event.data.title + 
           "'; with message '" + event.data.message + 
           "'; with data '" + event.data.data +"'" + 
           "'; from domain '" + event.data.domain + "'"); 
     }, false); 
    } 
    else { 
     // Here we get inside the iframes. 
     // We can address and check each iframe url with document.domain 

     document.body.style.backgroundColor = "#0f0"; // Just a UI change to identify the iframe window 

     // We change something inside the iframe 
     var dataDiv = document.getElementsByTagName('div')[0]; 
     dataDiv.innerHTML += " with a change!"; 

     // And we post a message to the top window with all the data we want inside an object 
     window.top.postMessage({ 
      title: document.title, 
      domain: document.domain, 
      message: "Hello from, iframe - " + document.title, 
      data: dataDiv.innerText 
     }, "*"); 
    } 

})(); 

Et une capture d'écran pour ceux qui n'ont pas Greasemonkey/Tampermoney installé pour tester ceci:

Script in action

PS: Il est pas valable pour ajouter des éléments directement dans une balise iframe comme ceci:

<iframe id="outer_iframe_2" src="https://subdomain2.example.com"> 
<div> 
    <iframe id="inner_iframe_2" src="https://subdomain4.example.com"></iframe> 
</div> 
</iframe> 
0

Ce n'est pas une réponse directe à votre question, mais ceci est pour ceux qui veulent utiliser javascript pour manipuler une page Web à des fins de traitement des données.

Les logiciels comme PhantomJS sont conçus pour "l'automatisation du navigateur" et permettent de supprimer complètement la politique d'origine croisée.

phantomjs.exe --web-security=no script.js 

Dans votre script, vous pouvez utiliser

page.open("http://fiddle.jshell.net/9aQv5/show/", function(status) { // Load a webpage 
    page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js", function() { // Add support jor jQuery 
     page.evaluate(function() { // Run custom script 
      console.log($("body").find("iframe").attr("src")); 

      console.log($("body").find("iframe").contents().find("iframe").attr("src")); 

      console.log($("body").find("iframe").contents().find("iframe").contents().find("#about-puppy-linux").html()); 
     }); 
     phantom.exit(0); 
    }); 
}); 

Vous obtenez la sortie suivante:

//fiddle.jshell.net/9aQv5/show/light/ 
http://www.puppylinux.com/ 
About Puppy Linux