Escapar cadenas HTML con jQuery


¿Alguien conoce una forma fácil de escapar HTML de cadenas en jQuery? Necesito ser capaz de pasar una cadena arbitraria y que se escape correctamente para mostrarla en una página HTML (evitando ataques de inyección de JavaScript/HTML). Estoy seguro de que es posible extender jQuery para hacer esto, pero no sé lo suficiente sobre el marco en este momento para lograr esto.

Author: Matt Fenwick, 2008-08-24

24 answers

Ya que estás usando jQuery , puedes simplemente establecer el text propiedad:

// before:
// <div class="someClass">text</div>
var someHtmlString = "<script>alert('hi!');</script>";

// set a DIV's text:
$("div.someClass").text(someHtmlString);
// after: 
// <div class="someClass">&lt;script&gt;alert('hi!');&lt;/script&gt;</div>

// get the text in a string:
var escaped = $("<div>").text(someHtmlString).html();
// value: 
// &lt;script&gt;alert('hi!');&lt;/script&gt;
 399
Author: travis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-07 10:09:33

También existe la solución del bigote.js

var entityMap = {
  '&': '&amp;',
  '<': '&lt;',
  '>': '&gt;',
  '"': '&quot;',
  "'": '&#39;',
  '/': '&#x2F;',
  '`': '&#x60;',
  '=': '&#x3D;'
};

function escapeHtml (string) {
  return String(string).replace(/[&<>"'`=\/]/g, function (s) {
    return entityMap[s];
  });
}
 538
Author: Tom Gruner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-13 19:14:50
$('<div/>').text('This is fun & stuff').html(); // "This is fun &amp; stuff"

Fuente: http://debuggable.com/posts/encode-html-entities-with-jquery:480f4dd6-13cc-4ce9-8071-4710cbdd56cb

 176
Author: Henrik N,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-25 22:36:06

Si estás escapando para HTML, solo hay tres que se me ocurren que serían realmente necesarios:

html.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");

Dependiendo de su caso de uso, es posible que también necesite hacer cosas como " a &quot;. Si la lista es lo suficientemente grande, solo usaría una matriz:

var escaped = html;
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]]
for(var item in findReplace)
    escaped = escaped.replace(findReplace[item][0], findReplace[item][1]);

encodeURIComponent() solo se escapará para URLs, no para HTML.

 58
Author: tghw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-08 14:18:19

Escribí una pequeña función que hace esto. Sólo se escapa ", &, < y > (pero por lo general eso es todo lo que necesita de todos modos). Es un poco más elegante que las soluciones propuestas anteriormente en que solo utiliza uno .replace() para hacer toda la conversión. (EDIT 2: Reduce la complejidad del código haciendo que la función sea aún más pequeña y ordenada, si tiene curiosidad por el código original, consulte el final de esta respuesta.)

function escapeHtml(text) {
    'use strict';
    return text.replace(/[\"&<>]/g, function (a) {
        return { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' }[a];
    });
}

Esto es Javascript simple, sin jQuery utilizar.

Escapando / y ' también

Editar en respuesta al comentario de mklement.

La función anterior se puede expandir fácilmente para incluir cualquier carácter. Para especificar más caracteres para escapar, simplemente insértelos tanto en la clase de caracteres en la expresión regular (es decir, dentro del /[...]/g) como como una entrada en el objeto chr. (EDIT 2: Acortó esta función también, de la misma manera.)

function escapeHtml(text) {
    'use strict';
    return text.replace(/[\"&'\/<>]/g, function (a) {
        return {
            '"': '&quot;', '&': '&amp;', "'": '&#39;',
            '/': '&#47;',  '<': '&lt;',  '>': '&gt;'
        }[a];
    });
}

Tenga en cuenta el uso anterior de &#39; para apóstrofe (la entidad simbólica &apos; podría haber sido utilizada en su lugar – está definida en XML, pero originalmente no estaba incluida en la especificación HTML y, por lo tanto, podría no ser compatible con todos los navegadores. Ver: Artículo de Wikipedia sobre codificaciones de caracteres HTML). También recuerdo haber leído en alguna parte que el uso de entidades decimales es más ampliamente soportado que el uso de hexadecimal, pero parece que no puedo encontrar la fuente para eso ahora. (Y no puede haber muchos navegadores por ahí que no soporta las entidades hexadecimales.)

Nota: Agregar / y 'a la lista de caracteres escapados no es tan útil, ya que no tienen ningún significado especial en HTML y no necesitan para ser escapados.

Original escapeHtml Función

EDITAR 2: La función original usaba una variable (chr) para almacenar el objeto necesario para la devolución de llamada .replace(). Esta variable también necesitaba una función anónima adicional para abarcarla, haciendo que la función un poco más grande y más complejo.

var escapeHtml = (function () {
    'use strict';
    var chr = { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' };
    return function (text) {
        return text.replace(/[\"&<>]/g, function (a) { return chr[a]; });
    };
}());

No he probado cuál de las dos versiones son más rápidas. Si lo hace, siéntase libre de agregar información y enlaces al respecto aquí.

 35
Author: zrajm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-19 15:03:50

Bastante fácil de usar:

_.escape(string) 

Underscore es una biblioteca de utilidades que proporciona muchas características que js nativo no proporciona. También hay lodash que es la misma API que underscore, pero se reescribió para tener más rendimiento.

 32
Author: chovy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-02 06:05:04

Me doy cuenta de lo tarde que llego a esta fiesta, pero tengo una solución muy fácil que no requiere jQuery.

escaped = new Option(unescaped).innerHTML;

Editar: Esto no escapa a las comillas. El único caso donde las comillas necesitan ser escapadas es si el contenido va a ser pegado en línea a un atributo dentro de una cadena HTML. Es difícil para mí imaginar un caso en el que hacer esto sería un buen diseño.

Edit 2: Si el rendimiento es crucial, la solución de mayor rendimiento (alrededor del 50%) sigue siendo una serie de expresiones regulares reemplazar. Los navegadores modernos detectarán que las expresiones regulares no contienen operadores, solo una cadena, y las colapsarán en una sola operación.

 30
Author: Adam Leggett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-08 20:28:27

Aquí hay una función JavaScript limpia y clara. Escapará texto como "unos pocos

function escapeHtmlEntities (str) {
  if (typeof jQuery !== 'undefined') {
    // Create an empty div to use as a container,
    // then put the raw text in and get the HTML
    // equivalent out.
    return jQuery('<div/>').text(str).html();
  }

  // No jQuery, so use string replace.
  return str
    .replace(/&/g, '&amp;')
    .replace(/>/g, '&gt;')
    .replace(/</g, '&lt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&apos;');
}
 26
Author: intrepidis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-20 17:56:57

Intenta Subrayar.string lib, funciona con jQuery.

_.str.escapeHTML('<div>Blah blah blah</div>')

Salida:

'&lt;div&gt;Blah blah blah&lt;/div&gt;'
 24
Author: Nikita Koksharov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-20 07:36:13

Después de las últimas pruebas puedo recomendar más rápido y completamente cross browser compatible javascript nativo (DOM) solución:

function HTMLescape(html){
    return document.createElement('div')
        .appendChild(document.createTextNode(html))
        .parentNode
        .innerHTML
}

Si lo repites muchas veces puedes hacerlo con variables una vez preparadas:

//prepare variables
var DOMtext = document.createTextNode("test");
var DOMnative = document.createElement("span");
DOMnative.appendChild(DOMtext);

//main work for each case
function HTMLescape(html){
  DOMtext.nodeValue = html;
  return DOMnative.innerHTML
}

Mira mi rendimiento final comparación (stack question ).

 23
Author: Saram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-07 10:54:05

He realzado el bigote.js ejemplo añadiendo el método escapeHTML() al objeto string.

var __entityMap = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': '&quot;',
    "'": '&#39;',
    "/": '&#x2F;'
};

String.prototype.escapeHTML = function() {
    return String(this).replace(/[&<>"'\/]/g, function (s) {
        return __entityMap[s];
    });
}

De esta manera es bastante fácil de usar "Some <text>, more Text&Text".escapeHTML()

 15
Author: Jeena,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-22 10:20:19

escape() y unescape() están destinados a codificar / decodificar cadenas para URLs, no HTML.

En realidad, uso el siguiente fragmento para hacer el truco que no requiere ningún marco:

var escapedHtml = html.replace(/&/g, '&amp;')
                      .replace(/>/g, '&gt;')
                      .replace(/</g, '&lt;')
                      .replace(/"/g, '&quot;')
                      .replace(/'/g, '&apos;');
 15
Author: NicolasBernier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-08 14:19:01

Si tiene subrayado.js, use _.escape (más eficiente que el método jQuery publicado anteriormente):

_.escape('Curly, Larry & Moe'); // returns: Curly, Larry &amp; Moe
 10
Author: ronnbot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-08 14:16:18

Si vas por la ruta regex, hay un error en el ejemplo de tghw anterior.

<!-- WON'T WORK -  item[0] is an index, not an item -->

var escaped = html; 
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g,"&gt;"], [/"/g,
"&quot;"]]

for(var item in findReplace) {
     escaped = escaped.replace(item[0], item[1]);   
}


<!-- WORKS - findReplace[item[]] correctly references contents -->

var escaped = html;
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]]

for(var item in findReplace) {
     escaped = escaped.replace(findReplace[item[0]], findReplace[item[1]]);
}
 5
Author: Wayne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-21 21:18:27

Este es un buen ejemplo seguro...

function escapeHtml(str) {
    if (typeof(str) == "string"){
        try{
            var newStr = "";
            var nextCode = 0;
            for (var i = 0;i < str.length;i++){
                nextCode = str.charCodeAt(i);
                if (nextCode > 0 && nextCode < 128){
                    newStr += "&#"+nextCode+";";
                }
                else{
                    newStr += "?";
                }
             }
             return newStr;
        }
        catch(err){
        }
    }
    else{
        return str;
    }
}
 4
Author: amrp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-31 01:31:02

Puedes hacerlo fácilmente con vanilla js.

Simplemente agregue un nodo de texto al documento. Será escapado por el navegador.

var escaped = document.createTextNode("<HTML TO/ESCAPE/>")
document.getElementById("[PARENT_NODE]").appendChild(escaped)
 3
Author: raam86,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-29 16:34:02
(function(undefined){
    var charsToReplace = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;'
    };

    var replaceReg = new RegExp("[" + Object.keys(charsToReplace).join("") + "]", "g");
    var replaceFn = function(tag){ return charsToReplace[tag] || tag; };

    var replaceRegF = function(replaceMap) {
        return (new RegExp("[" + Object.keys(charsToReplace).concat(Object.keys(replaceMap)).join("") + "]", "gi"));
    };
    var replaceFnF = function(replaceMap) {
        return function(tag){ return replaceMap[tag] || charsToReplace[tag] || tag; };
    };

    String.prototype.htmlEscape = function(replaceMap) {
        if (replaceMap === undefined) return this.replace(replaceReg, replaceFn);
        return this.replace(replaceRegF(replaceMap), replaceFnF(replaceMap));
    };
})();

No hay variables globales, alguna optimización de memoria. Uso:

"some<tag>and&symbol©".htmlEscape({'©': '&copy;'})

El resultado es:

"some&lt;tag&gt;and&amp;symbol&copy;"
 2
Author: Gheljenor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-13 11:21:59
function htmlEscape(str) {
    var stringval="";
    $.each(str, function (i, element) {
        alert(element);
        stringval += element
            .replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(' ', '-')
            .replace('?', '-')
            .replace(':', '-')
            .replace('|', '-')
            .replace('.', '-');
    });
    alert(stringval);
    return String(stringval);
}
 1
Author: Katharapu Ramana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-29 08:01:35

2 métodos simples que no requieren JQUERY...

Puedes codificar todos los caracteres en tu cadena así:

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

O simplemente destino de los personajes principales que preocuparse &, saltos de línea, <, >, " y ' como:

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

var myString='Encode HTML entities!\n"Safe" escape <script></'+'script> & other tags!';

test.value=encode(myString);

testing.innerHTML=encode(myString);

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<p><b>What JavaScript Generated:</b></p>

<textarea id=test rows="3" cols="55"></textarea>

<p><b>What It Renders Too In HTML:</b></p>

<div id="testing">www.WHAK.com</div>
 1
Author: Dave Brown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-08 14:14:43

Ejemplo de escape de JavaScript simple:

function escapeHtml(text) {
    var div = document.createElement('div');
    div.innerText = text;
    return div.innerHTML;
}

escapeHtml("<script>alert('hi!');</script>")
// "&lt;script&gt;alert('hi!');&lt;/script&gt;"
 1
Author: Andrew Luca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-29 08:23:38
function htmlDecode(t){
   if (t) return $('<div />').html(t).text();
}

Funciona como un encanto

 0
Author: d-_-b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-03 02:48:33

Esta respuesta proporciona los métodos jQuery y JS normales, pero esto es más corto sin usar el DOM:

unescape(escape("It's > 20% less complicated this way."))

Cadena de escape: It%27s%20%3E%2020%25%20less%20complicated%20this%20way.

Si los espacios escapados te molestan, prueba:

unescape(escape("It's > 20% less complicated this way.").replace(/%20/g, " "))

Cadena de escape: It%27s %3E 20%25 less complicated this way.

Desafortunadamente, la función escape() fueobsoleta en la versión 1.5 de JavaScript . encodeURI() o encodeURIComponent() son alternativas, pero ignoran ', por lo que la última línea de código se convertiría en esto:

decodeURI(encodeURI("It's > 20% less complicated this way.").replace(/%20/g, " ").replace("'", '%27'))

Todos los principales navegadores todavía admite el código corto, y dado el número de sitios web antiguos, dudo que eso cambie pronto.

 0
Author: Cees Timmerman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:46

Si está guardando esta información en una base de datos , es incorrecto escapar de HTML usando un script del lado del cliente, esto debe hacerse en el servidor . De lo contrario, es fácil eludir su protección XSS.

Para aclarar mi punto, aquí hay un ejemplo usando una de las respuestas:

Digamos que está utilizando la función escapeHtml para escapar del Html de un comentario en su blog y luego publicarlo en su servidor.

var entityMap = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': '&quot;',
    "'": '&#39;',
    "/": '&#x2F;'
  };

  function escapeHtml(string) {
    return String(string).replace(/[&<>"'\/]/g, function (s) {
      return entityMap[s];
    });
  }

El usuario podría:

  • Edite los parámetros de la solicitud POST y reemplace el comentario con código javascript.
  • Sobrescriba la función escapeHtml usando la consola del navegador.

Si el usuario pega este fragmento en la consola, omitirá la validación XSS:

function escapeHtml(string){
   return string
}
 -2
Author: Kauê Gimenes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-13 18:20:05

Todas las soluciones son inútiles si no impide que se vuelva a escapar, por ejemplo, la mayoría de las soluciones seguirían escapando & a &amp;.

escapeHtml = function (s) {
    return s ? s.replace(
        /[&<>'"]/g,
        function (c, offset, str) {
            if (c === "&") {
                var substr = str.substring(offset, offset + 6);
                if (/&(amp|lt|gt|apos|quot);/.test(substr)) {
                    // already escaped, do not re-escape
                    return c;
                }
            }
            return "&" + {
                "&": "amp",
                "<": "lt",
                ">": "gt",
                "'": "apos",
                '"': "quot"
            }[c] + ";";
        }
    ) : "";
};
 -2
Author: C Nimmanant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-08 14:15:24