Un moyen approprié d'exécuter JavaScript retourné via AJAX (pas jQuery)

Disent que je reçois une réponse à une demande de chargement AJAX de données avec un mélange de JavaScript et de HTML, par exemple:

<script>window.alert('Hello World!');</script> <p>This is a paragraph. Lorem ipsum dolor sit amet...</p> 

Si je place cette réponse dans un div ou un autre conteneur, le script ne s'exécute pas automatiquement. Je sais que cela peut se faire via la fonction eval() (comme indiqué dans l'exemple ci-dessous), mais eval est mauvais, alors, comment puis-je le faire correctement? Remarque: je n'utilise pas jQuery.

Voici un exemple de chargeur AJAX:

 function Load(id,url){ var ajax=new XMLHttpRequest(); ajax.onreadystatechange=function(){ if(ajax.readyState!=4)return; var obj=document.getElementById(id); if(!obj)return; obj.innerHTML=ajax.responseText; // load any scripts var s=obj.getElementsByTagName('script'); for(var i=0;i<s.length;++i)window.eval(s[i].innerHTML); // <-- bad } ajax.open("GET",url,true); ajax.send(null); } 

Notez que vous prenez des commentaires de l'utilisateur et l'exécutez dans le contexte d'un script sur votre site. Ainsi, le script peut faire tout ce que le JavaScript fonctionnant sur votre navigateur / domaine aurait la possibilité de faire (y compris le vol de cookie, XSS, les logiciels malveillants, etc.).

La seule chose que vous pouvez faire de façon réaliste pour atténuer les risques, c'est de ne pas utiliser eval () contenu fourni par l'utilisateur. Je suggérerais d'envisager les alternatives suivantes:

  1. Utilisez iframe comme environnement pour exécuter le script de l'utilisateur: http://dean.edwards.name/weblog/2006/11/sandbox/
  2. Utilisez Caja. Il permet aux sites Web d'intégrer en toute sécurité les applications Web DHTML à partir de tiers et permet une interaction riche entre la page d'intégration et les applications intégrées. Il utilise un modèle de sécurité à capacité d'objet pour permettre une large gamme de politiques de sécurité flexibles. http://code.google.com/p/google-caja/

Eval n'est pas particulièrement méchant dans ce scénario, ce n'est pas très différent de, disent, ajoutant dynamiquement une étiquette de script qui détruit un fichier .js et l'exécute. Cela dit, il existe d'autres options, par exemple, vous pouvez créer dynamiquement une étiquette de script, créer un nœud de texte avec le contenu de la balise de script que vous avez retirée et l'ajouter au document. Contrairement à la technique innerHTML, cela fonctionnera réellement le contenu. Le seul avantage sur eval, en fait, c'est que vous pourriez obtenir une trace de pile plus significative, etc. si elle se bloque ou a une erreur de syntaxe.

 var newScriptTag = document.createElement('script'); newScriptTag.appendChild(document.createTextNode( origScriptTag.innerHTML) document.body.appendChild(newScriptTag); 

J'ai résolu cela aujourd'hui en mettant mon JavaScript au bas de la réponse HTML.

J'ai eu une demande AJAX qui a renvoyé un tas de HTML qui a été affiché dans une superposition. Je devais attacher un événement de clic à un bouton dans la réponse HTML / recouvrement retourné. Sur une page normale, j'envelopperais mon JavaScript dans une "fenêtre.onload" ou "$ (document) .ready" afin d'attacher le gestionnaire d'événements à l'objet DOM après que le DOM pour la nouvelle superposition ait été rendu, mais Car il s'agissait d'une réponse AJAX et non d'une nouvelle charge de page, cet événement n'a jamais eu lieu, le navigateur n'a jamais exécuté mon JavaScript, mon gestionnaire d'événements n'a jamais été attaché à l'élément DOM et ma nouvelle fonctionnalité n'a pas fonctionné. Encore une fois, j'ai résolu mes "exécuter JavaScript dans un problème de réponse AJAX" en n'utilisant pas "$ (document) .ready" dans la tête du document, mais en plaçant mon JavaScript à la fin du document et en le faisant fonctionner après le HTML / DOM a été rendu.