2009-08-12 48 views
209

¿Hay alguna forma recomendada de escaparse de los caracteres <, >, " y & al generar HTML en código Java simple? (Aparte de hacer manualmente lo siguiente, eso es).Método recomendado para escaparse de HTML en Java

String source = "The less than sign (<) and ampersand (&) must be escaped before using them in HTML"; 
String escaped = source.replace("<", "&lt;").replace("&", "&amp;"); // ... 
+1

en cuenta que si está dando salida a un atributo HTML sin comillas, ese otro caracteres como espacio, tabulación, retroceso, etc. ... pueden permitir a los atacantes introducir atributos de JavaScript sin ninguno de los caracteres enumerados. Consulte la Hoja de referencia de prevención de OWASP XSS para obtener más información. –

Respuesta

223

StringEscapeUtils de Apache Commons Lang:

import static org.apache.commons.lang.StringEscapeUtils.escapeHtml; 
// ... 
String source = "The less than sign (<) and ampersand (&) must be escaped before using them in HTML"; 
String escaped = escapeHtml(source); 

Para version 3:

import static org.apache.commons.lang3.StringEscapeUtils.escapeHtml4; 
// ... 
String escaped = escapeHtml4(source); 
+2

Si bien 'StringEscapeUtils' es bueno, no escapará espacios en blanco correctamente para atributos si desea evitar la normalización de espacio en blanco HTML/XML. Ver mi respuesta para mayor detalle. –

+0

StringEscapeUtils.escapeHtml() solo acepta String como entrada, lo que parece innecesariamente rígido. En este mundo moderno de JSON, algunas cosas que salen a la página serán números, por ejemplo, en cuyo caso se rompe este método. – greim

+19

El ejemplo anterior está roto. Use el método escapeHtml4() ahora. – stackoverflowuser2010

108

Una alternativa a Apache Commons: Uso Spring 's HtmlUtils.htmlEscape(String input) método.

+8

Gracias. Lo he usado (en lugar de 'StringEscapeUtils.escapeHtml()' de 'apache-commons' 2.6) porque deja los caracteres rusos como están. –

+6

Eso es bueno saberlo. TBH. Le doy a Apache mucho espacio en estos días. – Adamski

+1

Lo he usado, también deja caracteres chinos como están, también. – smartwjw

12

Para algunos propósitos, HtmlUtils:

import org.springframework.web.util.HtmlUtils; 
[...] 
HtmlUtils.htmlEscapeDecimal("&")` //gives &#38; 
HtmlUtils.htmlEscape("&")` //gives &amp; 
45

Hay una versión más reciente del Apache Commons Lang library y utiliza un nombre de paquete (org.apache.commons.lang3). El StringEscapeUtils ahora tiene diferentes métodos estáticos para escaparse de diferentes tipos de documentos (http://commons.apache.org/proper/commons-lang/javadocs/api-3.0/index.html). Así que para escapar de la versión HTML 4.0 de la cadena:

import static org.apache.commons.lang3.StringEscapeUtils.escapeHtml4; 

String output = escapeHtml4("The less than sign (<) and ampersand (&) must be escaped before using them in HTML"); 
+1

Desafortunadamente, no existe nada para HTML 5, ni los documentos de Apache especifican si es correcto usar escapeHtml4 para HTML 5. –

32

Ten cuidado con esto. Hay varios "contextos" diferentes dentro de un documento HTML: dentro de un elemento, valor de atributo entrecomillado, valor de atributo sin comillas, atributo de URL, javascript, CSS, etc. Necesitará utilizar un método de codificación diferente para cada uno de ellos. estos para evitar Cross-Site Scripting (XSS). Consulte la Hoja de referencia de prevención de XSS de OWASP para obtener detalles sobre cada uno de estos contextos: https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet. Puede encontrar métodos de escape para cada uno de estos contextos en la biblioteca OWASP ESAPI - https://github.com/ESAPI/esapi-java-legacy.

+5

GRACIAS por señalar que el * contexto * en el que desea codificar la salida es muy importante. El término "codificar" también es un verbo mucho más apropiado que "escapar" también. Escape implica algún tipo de truco especial, en oposición a "¿cómo codifico * * esta cadena para: un atributo XHTML/parámetro de consulta SQL/cadena de impresión PostScript/campo de salida CSV? – Roboprog

+2

'Codificar' y 'escape' son ambos ampliamente utilizados El término "escape" se usa generalmente cuando el proceso consiste en agregar un "carácter de escape" antes de un carácter sintácticamente relevante, como el escape de un carácter de comillas con una barra invertida \ "El término" codificar "se usa más típicamente cuando traduce un personaje en una forma diferente, como la URL que codifica el carácter de cotización% 22 o la codificación de entidad HTML como & # x22 o @quot. –

+0

http://owasp-esapi-java.googlecode.com/svn/trunk_doc/latest/index.html. link now broke –

35

en Android (API 16 o mayor) se puede:

Html.escapeHtml(textToScape); 

o menor API:

TextUtils.htmlEncode(textToScape); 
+0

¿Hay alguna razón para usar 'escapeHtml' en lugar de' htmlEncode'? – Muz

+2

Vea también mi [mi pregunta] (http://stackoverflow.com/questions/35104032/whats-the-difference-between-androids-html-escapehtml-and-textutils-htmlencode) acerca de la diferencia entre estos dos. (@Muz) – JonasCz

10

Mientras @dfa respuesta de org.apache.commons.lang.StringEscapeUtils.escapeHtml es agradable y lo he utilizado en el pasado no se debe usar para escaparse de HTML (o XML) atributos de lo contrario, el espacio en blanco se normalizará (lo que significa que todos los espacios en blanco adyacentes se convierten en un solo espacio).

Lo sé porque he tenido errores encontrados en mi biblioteca (JATL) para los atributos donde el espacio en blanco no se ha conservado. Por lo tanto, tengo una gota en (copiar y pegar) class (of which I stole some from JDOM) that differentiates the escaping of attributes and element content.

Si bien esto puede no haber importado tanto en el pasado (escapando de atributos adecuados) es cada vez más interesante debido al uso del uso de los atributos de HTML5 data-.

47

Niza método abreviado:

public static String escapeHTML(String s) { 
    StringBuilder out = new StringBuilder(Math.max(16, s.length())); 
    for (int i = 0; i < s.length(); i++) { 
     char c = s.charAt(i); 
     if (c > 127 || c == '"' || c == '<' || c == '>' || c == '&') { 
      out.append("&#"); 
      out.append((int) c); 
      out.append(';'); 
     } else { 
      out.append(c); 
     } 
    } 
    return out.toString(); 
} 

Basado en https://stackoverflow.com/a/8838023/1199155 (el amplificador no se encuentra allí).Los cuatro caracteres controladas en el caso de la cláusula son los únicos por debajo de 128, de acuerdo con http://www.w3.org/TR/html4/sgml/entities.html

+0

Agradable. No utiliza las "versiones html" de las codificaciones (ejemplo: "á" sería "& aacute;" en lugar de "á"), pero dado que las numéricas funcionan incluso en IE7, supongo que no tengo que preocuparme . Gracias. – nonzaprej

27

Para aquellos que utilizan Google Guava:

import com.google.common.html.HtmlEscapers; 
[...] 
String source = "The less than sign (<) and ampersand (&) must be escaped before using them in HTML"; 
String escaped = HtmlEscapers.htmlEscaper().escape(source); 
Cuestiones relacionadas