web-dev-qa-db-fra.com

Échapper au HTML à l'aide de jQuery

J'ai trouvé un hack pour échapper au HTML en utilisant jQuery et je me demande si quelqu'un y voit un problème.

$('<i></i>').text(TEXT_TO_ESCAPE).html();

La balise <i> Est juste un mannequin car jQuery a besoin d'un conteneur pour définir le texte de.

Existe-t-il peut-être un moyen plus simple de procéder? Notez que j'ai besoin du texte stocké dans une variable, pas pour l'affichage (sinon je pourrais simplement appeler elem.text(TEXT_TO_ESCAPE);).

Merci!

37
Michael Mior

C'est une façon assez standard de le faire, ma version utilisait un <div> bien que:

return $('<div/>').text(t).html();

Ce n'est pas techniquement sûr à 100%, comme le note Mike Samuel, mais c'est probablement assez sûr dans la pratique.

Le Prototype.js actuel fait ceci:

function escapeHTML() {
    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
}

Mais il avait l'habitude d'utiliser l'astuce "mettre du texte dans un div et extraire le HTML".

Il y a aussi _.escape dans Underscore , cela se fait comme ceci:

// List of HTML entities for escaping.
var htmlEscapes = {
  '&': '&amp;',
  '<': '&lt;',
  '>': '&gt;',
  '"': '&quot;',
  "'": '&#x27;',
  '/': '&#x2F;'
};

// Regex containing the keys listed immediately above.
var htmlEscaper = /[&<>"'\/]/g;

// Escape a string for HTML interpolation.
_.escape = function(string) {
  return ('' + string).replace(htmlEscaper, function(match) {
    return htmlEscapes[match];
  });
};

C'est à peu près la même approche que celle de Prototype. La plupart du JavaScript que je fais récemment a Underscore disponible, j'ai donc tendance à utiliser _.escape ces jours-ci.

62
mu is too short

Il n'y a aucune garantie que html() sera complètement échappé donc le résultat pourrait ne pas être sûr après la concaténation.

html() est basé sur innerHTML, et un navigateur pourrait, sans violer beaucoup d'attentes, implémenter innerHTML pour que $("<i></i>").text("1 <").html() soit "1 <", et que $("<i></i>").text("b>").html() est "b>".

Ensuite, si vous concaténez ces deux résultats individuellement sûrs, vous obtenez "1 <b>" Qui ne sera évidemment pas la version HTML de la concaténation des deux éléments en clair.

Donc, cette méthode n'est pas sûre par déduction des premiers principes, et il n'y a pas de spécification largement suivie de innerHTML (bien que HTML5 la traite).

La meilleure façon de vérifier si elle fait ce que vous voulez est de tester des cas d'angle comme celui-ci.

11
Mike Samuel

Cela devrait fonctionner. C'est essentiellement la façon dont la bibliothèque Prototype.js le fait, ou du moins comment elle le faisait auparavant. Je le fais généralement avec trois appels à ".replace ()" mais c'est surtout juste une habitude.

1
Pointy