2009-08-12 29 views
209

Esiste un modo consigliato di sfuggire a <, , " e & caratteri durante l'emissione di codice HTML in codice Java semplice? (Oltre a fare manualmente quanto segue, cioè).Metodo consigliato per l'escape dell'HTML in 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

essere consapevoli del fatto che se si è l'output in un attributo HTML non quotate, che altro caratteri come spazio, tab, backspace, ecc ... possono consentire agli attaccanti di introdurre attributi javascript senza nessuno dei caratteri elencati. Per ulteriori informazioni, consulta il foglio di prevenzione della prevenzione XSS di OWASP. –

risposta

223

StringEscapeUtils da 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); 

Per version 3:

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

Mentre 'StringEscapeUtils' è bello, esso non sfuggirà correttamente agli spazi per gli attributi se si desidera evitare la normalizzazione degli spazi bianchi HTML/XML. Vedi la mia risposta per maggiori dettagli. –

+0

StringEscapeUtils.escapeHtml() accetta solo String come input, che sembra inutilmente rigido. In questo mondo moderno di JSON, alcune cose prodotte nella pagina saranno numeri, per esempio, nel qual caso questo metodo si interrompe. – greim

+19

L'esempio precedente è rotto. Utilizza ora il metodo escapeHtml4(). – stackoverflowuser2010

108

Un'alternativa alla Apache Commons: Usa Spring s' HtmlUtils.htmlEscape(String input) metodo.

+8

Grazie. L'ho usato (invece di 'StringEscapeUtils.escapeHtml()' da 'apache-commons' 2.6) perché lascia i caratteri russi così come sono. –

+6

Buono a sapersi. TBH Offro sempre più spazio ad Apache in questi giorni. – Adamski

+1

L'ho usato anch'io, lascia i caratteri cinesi così come sono. – smartwjw

12

Per alcuni scopi, HtmlUtils:

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

Esiste una versione più recente del Apache Commons Lang library e utilizza un nome di pacchetto diverso (org.apache.commons.lang3). Lo StringEscapeUtils ora ha diversi metodi statici per l'escape di diversi tipi di documenti (http://commons.apache.org/proper/commons-lang/javadocs/api-3.0/index.html). Quindi per evitare la stringa HTML versione 4.0:

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

Sfortunatamente non esiste nulla per HTML 5, né i documenti Apache specificano se è appropriato usare escapeHtml4 per HTML 5. –

32

Prestare attenzione a questo. Esistono diversi "contesti" all'interno di un documento HTML: all'interno di un elemento, il valore dell'attributo quotato, il valore dell'attributo non quotato, l'attributo URL, javascript, CSS, ecc. Dovrai utilizzare un metodo di codifica diverso per ciascuno di questi per prevenire Cross-Site Scripting (XSS). Controllare il foglio cheat di prevenzione di OWASP XSS per i dettagli su ciascuno di questi contesti - https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet. È possibile trovare i metodi di escaping per ciascuno di questi contesti nella libreria ESAPI OWASP - https://github.com/ESAPI/esapi-java-legacy.

+5

GRAZIE per aver sottolineato che il * contesto * in cui si desidera codificare l'output è molto importante. Anche il termine "codificare" è un verbo molto più appropriato di "escape". Escape implica una sorta di hack speciale, al contrario di "come faccio a * codificare * questa stringa per: un attributo XHTML/parametro query SQL/stringa di stampa PostScript/campo di output CSV? – Roboprog

+2

" Encode "e" escape "sono entrambi ampiamente utilizzati Il termine "escape" viene generalmente utilizzato quando il processo deve aggiungere un "carattere di escape" prima di un carattere sintatticamente rilevante, come ad esempio l'escape di un carattere di citazione con una barra rovesciata \ "Il termine" encode "è più tipicamente usato quando traduci un personaggio in una forma diversa, come la codifica URL del carattere di citazione% 22 o codifica di entità HTML come & # x22 o @quot. –

+0

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

35

su Android (API 16 o superiore) è possibile:

Html.escapeHtml(textToScape); 

o inferiore API:

TextUtils.htmlEncode(textToScape); 
+0

C'è qualche ragione per usare 'escapeHtml' invece di' htmlEncode'? – Muz

+2

Vedere anche la mia [la mia domanda] (http://stackoverflow.com/questions/35104032/whats-the-difference-between-androids-html-escapehtml-and-textutils-htmlencode) sulla differenza tra questi due. (@Muz) – JonasCz

10

Mentre @dfa risposta di org.apache.commons.lang.StringEscapeUtils.escapeHtml è bello e ho usato in passato non dovrebbe essere usato per l'escape di attributi HTML (o XML) altrimenti lo spazio bianco verrà normalizzato (ovvero tutti i caratteri spazi bianchi adiacenti diventeranno un singolo spazio).

Lo so perché ho avuto bug archiviati contro la mia libreria (JATL) per gli attributi in cui lo spazio non è stato conservato. Così ho un calo (copia e incolla) class (of which I stole some from JDOM) that differentiates the escaping of attributes and element content.

Anche se questo potrebbe non aver avuto importanza in passato (corretta attribuzione di escape) è sempre più di maggiore interesse, dato l'uso dell'uso degli attributi di HTML5 data-.

47

Nizza metodo breve:

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(); 
} 

Sulla base https://stackoverflow.com/a/8838023/1199155 (l'amplificatore manca lì).I quattro personaggi controllato nella clausola if sono gli unici sotto 128, secondo http://www.w3.org/TR/html4/sgml/entities.html

+0

Bello. Non usa le "versioni html" delle codifiche (esempio: "á" sarebbe "& aacute" invece di "á"), ma dal momento che quelle numeriche funzionano anche in IE7, immagino di non dovermi preoccupare . Grazie. – nonzaprej

27

Per coloro che utilizzano 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); 
Problemi correlati