web-dev-qa-db-fra.com

Comment puis-je échapper au HTML en javascript?

Vu le texte

<b>This is some text</b>

Je veux l'écrire sur ma page pour qu'elle apparaisse comme ceci:

<b>This is some text</b>

et pas comme ça

Ceci est du texte

en utilisant escape("<b>This is some text</b>") me donne ce joli bijou dans Firefox

%3Cb%3EThis%20is%20some%20text%3C/b%3E

pas exactement ce que je recherche. Des idées?

25
Micah

Cela devrait fonctionner pour vous: http://blog.nickburwell.com/2011/02/escape-html-tags-in-javascript.html

function escapeHTML( string )
{
    var pre = document.createElement('pre');
    var text = document.createTextNode( string );
    pre.appendChild(text);
    return pre.innerHTML;
}

Avertissement de sécurité

La fonction n'échappe pas aux guillemets simples et doubles qui, s'ils sont utilisés dans le mauvais contexte, peuvent toujours conduire à XSS. Par exemple:

 var userWebsite = '" onmouseover="alert(\'gotcha\')" "';
 var profileLink = '<a href="' + escapeHtml(userWebsite) + '">Bob</a>';
 var div = document.getElemenetById('target');
 div.innerHtml = profileLink;
 // <a href="" onmouseover="alert('gotcha')" "">Bob</a>

Merci à buffer pour avoir signalé ce cas. Extrait extrait de cet article de blog .

58
limc

J'ai fini par faire ça:

function escapeHTML(s) { 
    return s.replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;');
}
29
Michele Bosi

J'aime la réponse de @ limc pour les situations où le document HTML DOM est disponible.

J'aime les réponses de @Michele Bosi et @ Paolo pour un environnement de document DOM non HTML tel que Node.js.

La réponse de @Michael Bosi peut être optimisée en supprimant la nécessité d'appeler replace 4 fois avec une seule invocation de replace combinée à une fonction de remplacement intelligente:

function escape(s) {
    let lookup = {
        '&': "&amp;",
        '"': "&quot;",
        '<': "&lt;",
        '>': "&gt;"
    };
    return s.replace( /[&"<>]/g, (c) => lookup[c] );
}
console.log(escape("<b>This is some text.</b>"));

Le test de portée de @ Paolo peut être optimisé avec une expression rationnelle bien choisie et la boucle for peut être éliminée en utilisant une fonction de remplacement:

function escape(s) {
    return s.replace(
        /[^0-9A-Za-z ]/g,
        c => "&#" + c.charCodeAt(0) + ";"
    );
}
console.log(escape("<b>This is some text</b>"));

Comme @Paolo l'a indiqué, cette stratégie fonctionnera pour plus de scénarios.

20
Stephen Quan

Évasion traditionnelle

Si vous utilisez XHTML, vous devrez utiliser une section CDATA. Vous pouvez également les utiliser en HTML, mais le HTML n'est pas aussi strict.

J'ai divisé les constantes de chaîne afin que ce code fonctionne en ligne sur XHTML dans les blocs CDATA. Si vous vous approvisionnez en JavaScript dans des fichiers séparés, vous n'avez pas besoin de vous en préoccuper. Notez que si vous êtes en utilisant XHTML avec JavaScript en ligne, alors vous avez besoin pour enfermer votre code dans un bloc CDATA, ou une partie de cela ne fonctionnera pas. Vous rencontrerez des erreurs étranges et subtiles.

function htmlentities(text) {
    var escaped = text.replace(/\]\]>/g, ']]' + '>]]&gt;<' + '![CDATA[');
    return '<' + '![CDATA[' + escaped + ']]' + '>';
}

Nœud de texte DOM

La manière "correcte" d'échapper du texte est d'utiliser la fonction DOM document.createTextNode. Cela n'échappe pas réellement au texte; il indique simplement au navigateur de créer un élément de texte, qui est intrinsèquement non analysé. Vous devez cependant être disposé à utiliser le DOM pour que cette méthode fonctionne: c'est-à-dire que vous devez utiliser des méthodes telles que appendChild, par opposition à la propriété innerHTML et similaire. Cela remplirait un élément avec l'ID an-element avec du texte, qui ne serait pas analysé en tant que (X) HTML:

var textNode = document.createTextNode("<strong>This won't be bold.  The tags " +
    "will be visible.</strong>");
document.getElementById('an-element').appendChild(textNode);

jQuery DOM Wrapper

jQuery fournit un wrapper pratique pour createTextNode nommé text. C'est assez pratique. Voici la même fonctionnalité à l'aide de jQuery:

$('#an-element').text("<strong>This won't be bold.  The tags will be " +
    "visible.</strong>");
3
Zenexer

Voici une fonction qui remplace les crochets angulaires par leurs entités html. Vous voudrez peut-être l'étendre pour inclure d'autres personnages également.

function htmlEntities( html ) {
    html = html.replace( /[<>]/g, function( match ) {
        if( match === '<' ) return '&lt;';
        else return '&gt;';
    });
    return html;
}

console.log( htmlEntities( '<b>replaced</b>' ) ); // &lt;b&gt;replaced&lt;/b&gt;
2
meouw

Vous pouvez encoder tous les caractères de votre chaîne:

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}

Ou ciblez simplement les personnages principaux dont vous devez vous soucier (&, inebreaks, <,>, "et ') comme:

function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}

test.value=encode('Encode HTML entities!\n\n"Safe" escape <script id=\'\'> & useful in <pre> tags!');

testing.innerHTML=test.value;

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<textarea id=test rows="9" cols="55"></textarea>

<div id="testing">www.WHAK.com</div>
2
Dave Brown

Essayez ceci htmlentities for javascript

function htmlEntities(str) {
    return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}
2
Headshota

J'utilise la fonction suivante qui échappe à chaque caractère avec la notation & # nnn ; sauf az AZ 0- 9 et espace

function Escape( s )
{
    var h,
        i,
        n,
        c;

    n = s.length;
    h = '';

    for( i = 0; i < n; i++ )
    {
        c = s.charCodeAt( i );
        if( ( c >= 48 && c <= 57 ) 
          ||( c >= 65 && c <= 90 ) 
          ||( c >= 97 && c <=122 )
          ||( c == 32 ) )
        {
            h += String.fromCharCode( c );
        }
        else
        {
            h += '&#' + c + ';';
        }
    }

    return h;
}

Exemple:

Escape('<b>This is some text</b>')

retour

&#60;b&#62;This is some text&#60;&#47;b&#62;

La fonction est la preuve des attaques par injection de code, la preuve unicode, le JavaScript pur.

Cette approche est environ 50 fois plus lente que celle qui crée le nœud de texte DOM, mais la fonction échappe toujours à une chaîne d'un million (1 000 000) de caractères en 100-150 millisecondes.

(Testé au début de 2011 MacBook Pro - Safari 9 - Mavericks)

1
Paolo