con - string to html javascript
Escapar de cadenas HTML con jQuery (24)
Aquí hay una función de JavaScript limpia y clara. Escapará texto como "unos pocos <muchos" en "unos pocos & lt; muchos".
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, ''&'')
.replace(/>/g, ''>'')
.replace(/</g, ''<'')
.replace(/"/g, ''"'')
.replace(/''/g, ''''');
}
¿Alguien sabe de una manera fácil de escapar de HTML de cadenas en jQuery ? Necesito poder pasar una cadena arbitraria y hacer 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 lograrlo.
Bastante fácil de usar subrayado:
_.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 el guión bajo, pero se reescribió para ser más lodash .
Después de las últimas pruebas, puedo recomendar la solución nativa javaScript (DOM) más rápida y completamente compatible con todos los navegadores :
function HTMLescape(html){
return document.createElement(''div'')
.appendChild(document.createTextNode(html))
.parentNode
.innerHTML
}
Si lo repites muchas veces, puedes hacerlo con variables preparadas una vez:
//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 comparison rendimiento final ( pila de preguntas ).
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>")
// "<script>alert(''hi!'');</script>"
Escribí una pequeña función que hace esto. Solo se escapa "
, &
, <
y >
(pero, por lo general, eso es todo lo que necesita). Es un poco más elegante que las soluciones propuestas anteriormente, ya que solo usa un .replace()
para hacer toda la conversión. ( EDIT 2: La complejidad reducida del código hace que la función sea aún más pequeña y ordenada, si tiene curiosidad sobre el código original, vea el final de esta respuesta.
function escapeHtml(text) {
''use strict'';
return text.replace(/[/"&<>]/g, function (a) {
return { ''"'': ''"'', ''&'': ''&'', ''<'': ''<'', ''>'': ''>'' }[a];
});
}
Esto es Javascript simple, no jQuery utilizado.
Escapando /
y ''
también
Editar en respuesta al comentario de mklement .
La función anterior se puede ampliar fácilmente para incluir cualquier carácter. Para especificar más caracteres de los que escapar, simplemente insértelos tanto en la clase de caracteres en la expresión regular (es decir, dentro del / /[...]/g
) 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 {
''"'': ''"'', ''&'': ''&'', "''": ''''',
''/'': ''/'', ''<'': ''<'', ''>'': ''>''
}[a];
});
}
Tenga en cuenta el uso anterior de '
para apóstrofe (la entidad simbólica '
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. Consulte: 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 compatible que el uso de hexadecimal, pero parece que ahora no puedo encontrar la fuente para eso. (Y no puede haber muchos navegadores que no admitan 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 ser escapados.
Función original de escapeHtml
EDIT 2: la función original usó 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 su alcance, haciendo que la función (innecesariamente) fuera un poco más grande y más compleja.
var escapeHtml = (function () {
''use strict'';
var chr = { ''"'': ''"'', ''&'': ''&'', ''<'': ''<'', ''>'': ''>'' };
return function (text) {
return text.replace(/[/"&<>]/g, function (a) { return chr[a]; });
};
}());
No he probado cuál de las dos versiones es más rápida. Si lo hace, siéntase libre de agregar información y enlaces al respecto aquí.
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;
}
}
He mejorado el ejemplo de escapeHTML()
al agregar el método escapeHTML()
al objeto de cadena.
var __entityMap = {
"&": "&",
"<": "<",
">": ">",
''"'': ''"'',
"''": ''''',
"/": ''/''
};
String.prototype.escapeHTML = function() {
return String(this).replace(/[&<>"''//]/g, function (s) {
return __entityMap[s];
});
}
De esa manera es bastante fácil de usar "Some <text>, more Text&Text".escapeHTML()
Me doy cuenta de lo tarde que estoy en esta fiesta, pero tengo una solución muy fácil que no requiere jQuery.
escaped = new Option(unescaped).innerHTML;
Edición: Esto no escapa de las comillas. El único caso en el que las comillas tendrían que escaparse es si el contenido se pegará en línea a un atributo dentro de una cadena HTML. Me resulta difícil imaginar un caso en el que hacer esto sea un buen diseño.
Edición 2: si el rendimiento es crucial, la solución de mayor rendimiento (alrededor del 50%) sigue siendo una serie de reemplazos de expresiones regulares. Los navegadores modernos detectarán que las expresiones regulares no contienen operadores, solo una cadena, y las colapsarán todas en una sola operación.
Prueba Underscore.string lib, funciona con jQuery.
_.str.escapeHTML(''<div>Blah blah blah</div>'')
salida:
''<div>Blah blah blah</div>''
Puedes hacerlo fácilmente con vainilla js.
Simplemente añada un nodo de texto al documento. Será escapado por el navegador.
var escaped = document.createTextNode("<HTML TO/ESCAPE/>")
document.getElementById("[PARENT_NODE]").appendChild(escaped)
Si está escapando para HTML, solo hay tres que puedo pensar que serían realmente necesarias:
html.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
Dependiendo de su caso de uso, es posible que también necesite hacer cosas como "
a "
"
si la lista fuera lo suficientemente grande, solo usaría una matriz:
var escaped = html;
var findReplace = [[/&/g, "&"], [/</g, "<"], [/>/g, ">"], [/"/g, """]]
for(var item in findReplace)
escaped = escaped.replace(findReplace[item][0], findReplace[item][1]);
encodeURIComponent()
solo lo escapará para las URL, no para HTML.
Si está guardando esta información en una base de datos , es incorrecto escapar de HTML usando una secuencia de comandos del lado del cliente , esto debe hacerse en el servidor . De lo contrario es fácil pasar por alto su protección XSS.
Para aclarar mi punto, aquí hay un ejemplo que usa 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 = {
"&": "&",
"<": "<",
">": ">",
''"'': ''"'',
"''": ''''',
"/": ''/''
};
function escapeHtml(string) {
return String(string).replace(/[&<>"''//]/g, function (s) {
return entityMap[s];
});
}
El usuario podría:
- Edite los parámetros de solicitud POST y reemplace el comentario con código javascript.
- Sobrescriba la función escapeHtml utilizando la consola del navegador.
Si el usuario pega este fragmento en la consola, omitirá la validación XSS:
function escapeHtml(string){
return string
}
Si tiene subrayado.js, use _.escape
(más eficiente que el método jQuery publicado anteriormente):
_.escape(''Curly, Larry & Moe''); // returns: Curly, Larry & Moe
Si va por la ruta de expresiones regulares, hay un error en el ejemplo anterior de tghw.
<!-- WON''T WORK - item[0] is an index, not an item -->
var escaped = html;
var findReplace = [[/&/g, "&"], [/</g, "<"], [/>/g,">"], [/"/g,
"""]]
for(var item in findReplace) {
escaped = escaped.replace(item[0], item[1]);
}
<!-- WORKS - findReplace[item[]] correctly references contents -->
var escaped = html;
var findReplace = [[/&/g, "&"], [/</g, "<"], [/>/g, ">"], [/"/g, """]]
for(var item in findReplace) {
escaped = escaped.replace(findReplace[item[0]], findReplace[item[1]]);
}
También existe la solución de mustache.js.
var entityMap = {
''&'': ''&'',
''<'': ''<'',
''>'': ''>'',
''"'': ''"'',
"''": ''''',
''/'': ''/'',
''`'': ''`'',
''='': ''=''
};
function escapeHtml (string) {
return String(string).replace(/[&<>"''`=//]/g, function (s) {
return entityMap[s];
});
}
Todas las soluciones son inútiles si no evita que vuelvan a escapar, por ejemplo, la mayoría de las soluciones seguirían escapando &
to &
.
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] + ";";
}
) : "";
};
escape()
y unescape()
están destinados a codificar / decodificar cadenas para URL, no HTML.
En realidad, utilizo el siguiente fragmento de código para hacer el truco que no requiere ningún marco:
var escapedHtml = html.replace(/&/g, ''&'')
.replace(/>/g, ''>'')
.replace(/</g, ''<'')
.replace(/"/g, ''"'')
.replace(/''/g, ''''');
2 métodos simples que requieren NO JQUERY ...
Puedes codificar todos los caracteres en tu cadena de esta manera:
function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}
O simplemente apunte a los personajes principales para preocuparse por &
, 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 &ersand (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>
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 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()
fue obsoleta 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 siguen admitiendo el código corto y, dada la cantidad de sitios web antiguos, dudo que eso cambie pronto.
Ya que estás usando jQuery , puedes establecer la propiedad de text
del elemento:
// 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"><script>alert(''hi!'');</script></div>
// get the text in a string:
var escaped = $("<div>").text(someHtmlString).html();
// value:
// <script>alert(''hi!'');</script>
$(''<div/>'').text(''This is fun & stuff'').html(); // "This is fun & stuff"
Fuente: http://debuggable.com/posts/encode-html-entities-with-jquery:480f4dd6-13cc-4ce9-8071-4710cbdd56cb
(function(undefined){
var charsToReplace = {
''&'': ''&'',
''<'': ''<'',
''>'': ''>''
};
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));
};
})();
Sin variables globales, alguna optimización de memoria. Uso:
"some<tag>and&symbol©".htmlEscape({''©'': ''©''})
el resultado es:
"some<tag>and&symbol©"
function htmlDecode(t){
if (t) return $(''<div />'').html(t).text();
}
Funciona de maravilla
function htmlEscape(str) {
var stringval="";
$.each(str, function (i, element) {
alert(element);
stringval += element
.replace(/&/g, ''&'')
.replace(/"/g, ''"'')
.replace(/''/g, ''''')
.replace(/</g, ''<'')
.replace(/>/g, ''>'')
.replace('' '', ''-'')
.replace(''?'', ''-'')
.replace('':'', ''-'')
.replace(''|'', ''-'')
.replace(''.'', ''-'');
});
alert(stringval);
return String(stringval);
}