web-dev-qa-db-fra.com

SecurityError: blocage d'un cadre avec Origin pour l'accès à un cadre croisé.

Je charge un <iframe> dans ma page HTML et j'essaie d'accéder aux éléments qu'il contient à l'aide de Javascript, mais lorsque j'essaie d'exécuter mon code, le message d'erreur suivant s'affiche:

SecurityError: Blocked a frame with Origin "http://www.<domain>.com" from accessing a cross-Origin frame.

Pouvez-vous m'aider à trouver une solution pour pouvoir accéder aux éléments du cadre?

J'utilise ce code pour tester, mais en vain:

$(document).ready(function() {
    var iframeWindow = document.getElementById("my-iframe-id").contentWindow;

    iframeWindow.addEventListener("load", function() {
        var doc = iframe.contentDocument || iframe.contentWindow.document;
        var target = doc.getElementById("my-target-id");

        target.innerHTML = "Found it!";
    });
});
450
mubashermubi

Politique de même origine

Ne pas confondre avec CORS !

Vous ne pouvez pas accéder à un _<iframe>_ avec une origine différente à l'aide de JavaScript, ce serait une faille de sécurité énorme si vous pouviez le faire. Pour les règle de même origine, les navigateurs bloquent les scripts qui tentent d'accéder à un cadre ayant une origine différente .

L'origine est considérée différente si au moins une des parties suivantes de l'adresse n'est pas conservée:

_<protocol>://<hostname>:<port>/path/to/page.html 
_

Protocole , nom d'hôte et port doit être identique à votre domaine si vous souhaitez accéder à un cadre.

Exemples

Voici ce qui arriverait en essayant d'accéder aux URL suivantes à partir de _http://www.example.com/home/index.html_

_URL                                             RESULT 
http://www.example.com/home/other.html       -> Success 
http://www.example.com/dir/inner/another.php -> Success 
http://www.example.com:80                    -> Success (default port for HTTP) 
http://www.example.com:2251                  -> Failure: different port 
http://data.example.com/dir/other.html       -> Failure: different hostname 
https://www.example.com/home/index.html.html -> Failure: different protocol 
ftp://www.example.com:21                     -> Failure: different protocol & port 
https://google.com/search?q=james+bond       -> Failure: different hostname & protocol 
_

Workaround

Même si la politique de même origine empêche les scripts d'accéder au contenu de sites ayant une origine différente , si vous possédez les deux pages, vous pouvez contourner ce problème à l'aide de window.postMessage et son événement relatif message pour envoyer des messages entre les deux pages, comme ceci:

  • Dans votre page principale:

    _let frame = document.getElementById('your-frame-id'); 
    
    frame.contentWindow.postMessage(/*any variable or object here*/, '*'); 
    _
  • Dans votre _<iframe>_ (contenu dans la page principale):

    _window.addEventListener('message', function(event) { 
    
        // IMPORTANT: Check the Origin of the data! 
        if (~event.Origin.indexOf('http://yoursite.com')) { 
            // The data has been sent from your site 
    
            // The data sent with postMessage is stored in event.data 
            console.log(event.data); 
        } else { 
            // The data hasn't been sent from your site! 
            // Be careful! Do not use it. 
            return; 
        } 
    }); 
    _

Cette méthode peut être appliquée dans les deux directions , en créant également un écouteur sur la page principale et en recevant des réponses de la base. La même logique peut également être implémentée dans les fenêtres contextuelles et, fondamentalement, dans toute nouvelle fenêtre générée par la page principale (par exemple, en utilisant window.open() ) également, sans aucune différence.

Désactivation de la stratégie de même origine dans votre navigateur

Il existe déjà de bonnes réponses à ce sujet (je viens de les trouver sur Google), aussi, pour les navigateurs où cela est possible, je vais relier la réponse relative. Cependant, rappelez-vous que la désactivation de la politique de même origine (ou du CORS) n’affectera que votre navigateur . En outre, l’exécution d’un navigateur avec des paramètres de sécurité identiques à l’origine désactivée accorde à tout accès des sites Web aux ressources croisées, de sorte que est très dangereux et devrait être supprimé. fait à des fins de développement uniquement .

691
Marco Bonelli

Complément de la réponse de Marco Bonelli: le meilleur moyen d'interagir actuellement entre les cadres/iframes est d'utiliser window.postMessage , pris en charge par tous les navigateurs

49
Geert

Vérifiez le serveur Web du domaine pour http://www.<domain>.com configuration pour X-Frame-Options Il s'agit d'une fonctionnalité de sécurité conçue pour empêcher les attaques de clickJacking,

Comment fonctionne clickJacking?

  1. La page du mal ressemble exactement à la page de la victime.
  2. Ensuite, il a trompé les utilisateurs en leur demandant d'entrer leur nom d'utilisateur et leur mot de passe.

Techniquement, la perversité a un iframe avec le source de la page de victime.

<html>
    <iframe src='victim_domain.com'/>
    <input id="username" type="text" style="display: none;/>
    <input id="password" type="text" style="display: none;/>
    <script>
        //some JS code that click jacking the user username and input from inside the iframe...
    <script/>
<html>

Comment fonctionne la fonction de sécurité

Si vous souhaitez empêcher le rendu de la requête du serveur Web dans un iframe ajoutez le x-frame-options

X-Frame-Options DENY

Les options sont:

  1. SAMEORIGIN // n'autorise que mon propre domaine à rendre mon code HTML à l'intérieur d'un iframe.
  2. DENY // n'autorise pas le rendu de mon code HTML dans une iframe
  3. "ALLOW-FROM https://example.com/ " // autorise un domaine spécifique à rendre mon code HTML à l'intérieur d'un iframe

Ceci est IIS exemple de configuration:

   <httpProtocol>
       <customHeaders>
           <add name="X-Frame-Options" value="SAMEORIGIN" />
       </customHeaders>
   </httpProtocol>

La solution à la question

Si le serveur Web a activé la fonctionnalité de sécurité, cela peut provoquer une erreur SecurityError côté client comme il se doit.

16
Shahar Shokrani

Pour moi, je voulais mettre en place une poignée de main à double sens, ce qui signifie:
- la fenêtre parente se chargera plus rapidement que l'iframe
- l’iframe devrait parler à la fenêtre parente dès que sa fenêtre est prête.
- le parent est prêt à recevoir le message iframe et à le rejouer

ce code est utilisé pour définir une étiquette blanche dans l'iframe à l'aide de [propriété personnalisée CSS]
code:
iframe

$(function() {
    window.onload = function() {
        // create listener
        function receiveMessage(e) {
            document.documentElement.style.setProperty('--header_bg', e.data.wl.header_bg);
            document.documentElement.style.setProperty('--header_text', e.data.wl.header_text);
            document.documentElement.style.setProperty('--button_bg', e.data.wl.button_bg);
            //alert(e.data.data.header_bg);
        }
        window.addEventListener('message', receiveMessage);
        // call parent
        parent.postMessage("GetWhiteLabel","*");
    }
});

parent

$(function() {
    // create listener
    var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
    var eventer = window[eventMethod];
    var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
    eventer(messageEvent, function (e) {
        // replay to child (iframe) 
        document.getElementById('wrapper-iframe').contentWindow.postMessage(
            {
                event_id: 'white_label_message',
                wl: {
                    header_bg: $('#Header').css('background-color'),
                    header_text: $('#Header .HoverMenu a').css('color'),
                    button_bg: $('#Header .HoverMenu a').css('background-color')
                }
            },
            '*'
        );
    }, false);
});

naturellement, vous pouvez limiter les origines et le texte, il est facile de travailler avec du code
J'ai trouvé cet exemple utile:
[[Messagerie inter-domaines avec postMessage]

7
Yakir Manor