2009-08-12 1 views
209

Есть ли способ избежать вывода <, >, " и & символов при выводе HTML в виде простого кода Java? (За исключением ручного выполнения следующего, то есть).Рекомендуемый метод ускорения HTML в 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

Имейте в виду, что если вы вывода в некотируемого атрибут HTML, что другие символы, такие как пробел, табуляция, backspace и т. д., могут позволить атакующим вводить атрибуты javascript без каких-либо символов. Более подробную информацию см. В Обзоре Cheat OWASP XSS. –

ответ

223

StringEscapeUtils от 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); 

Для version 3:

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

В то время как 'StringEscapeUtils' хорош, он не сможет избежать пробелов должным образом для атрибутов, если вы хотите избежать нормализации пробелов HTML/XML. См. Мой ответ для более подробной информации. –

+0

StringEscapeUtils.escapeHtml() принимает только String как входной сигнал, который кажется излишне жестким. В этом современном мире JSON некоторые вещи, выводимые на страницу, будут, например, числами, и в этом случае этот метод ломается. – greim

+19

Вышеприведенный пример нарушен. Теперь используйте метод escapeHtml4(). – stackoverflowuser2010

108

В качестве альтернативы Apache Commons: HtmlUtils.htmlEscape(String input) метод использования Spring «ы.

+8

Спасибо. Я использовал его (вместо 'StringEscapeUtils.escapeHtml()' из 'apache-commons' 2.6), потому что он оставляет русские символы как есть. –

+6

Это полезно знать. TBH Я даю Apache материал широкий причал в эти дни. – Adamski

+1

Я тоже использовал его, он также оставляет китайские иероглифы. – smartwjw

12

Для некоторых целей HtmlUtils:

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

Существует более новая версия Apache Commons Lang library и он использует другое имя пакета (org.apache.commons.lang3). StringEscapeUtils теперь имеет разные статические методы для экранирования различных типов документов (http://commons.apache.org/proper/commons-lang/javadocs/api-3.0/index.html). Таким образом, чтобы избежать строки HTML версии 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

К сожалению, ничего не существует для HTML 5, и документы Apache не указывают, правильно ли использовать escapeHtml4 для HTML 5. –

32

Будьте осторожны с этим. Внутри HTML-документа имеется несколько разных «контекстов»: внутри элемента, значение цитируемого атрибута, значение без кавычек, атрибут URL, javascript, CSS и т. Д. Вам нужно будет использовать другой метод кодирования для каждого из чтобы предотвратить межсайтовый скриптинг (XSS). Для получения более подробной информации о каждом из этих контекстов проверьте OWASP XSS Prevention Cheat Sheet - https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet. Вы можете найти методы экранирования для каждого из этих контекстов в библиотеке OWASP ESAPI - https://github.com/ESAPI/esapi-java-legacy.

+5

СПАСИБО за то, что * контекст *, в который вы хотите кодировать вывод, имеет большое значение. Термин «кодировать» также является гораздо более подходящим глаголом, чем «побег». Escape подразумевает какой-то особый хак, в отличие от «как я * кодирую * эту строку для: атрибута XHTML/параметра запроса SQL/строки PostScript print/CSV? – Roboprog

+2

« Encode »и« escape »широко используются чтобы описать это. Термин «побег» обычно используется, когда процесс заключается в том, чтобы добавить «escape-символ» перед синтаксически-значимым символом, например, экранировать символ кавычки с обратным слэшем. «Термин« кодирование »более типично используется когда вы переводите символ в другую форму, такую ​​как URL-код, кодирующий символ кавычки% 22 или кодирование сущности HTML как & # x22 или @quot. –

+0

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

35

на андроид (API 16 или больше) вы можете:

Html.escapeHtml(textToScape); 

или нижней API:

TextUtils.htmlEncode(textToScape); 
+0

Есть ли причина использовать 'escapeHtml' вместо' htmlEncode'? – Muz

+2

См. Также мой [мой вопрос] (http://stackoverflow.com/questions/35104032/whats-the-difference-between-androids-html-escapehtml-and-textutils-htmlencode) о различии между этими двумя. (@Muz) – JonasCz

10

Хотя @dfa ответ org.apache.commons.lang.StringEscapeUtils.escapeHtml хорошо, и я использовал его в прошлом он не должен использоваться для экранирования атрибутов HTML (или XML) , иначе пробелы будут нормализованы (это означает, что все смежные пробельные символы становятся единым пространством).

Я знаю это, потому что у меня были ошибки, связанные с моей библиотекой (JATL) для атрибутов, где пробелы не сохранялись. Таким образом, у меня есть капля (копия n 'paste) class (of which I stole some from JDOM) that differentiates the escaping of attributes and element content.

Хотя это, возможно, не так важно в прошлом (надлежащий атрибут экранирования), он становится все более интересным, учитывая использование использования атрибута HTML5 data-.

47

Nice короткий метод:

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

на основе https://stackoverflow.com/a/8838023/1199155 (усилитель отсутствует там).Четыре символа проверяются в, если п являются единственными ниже 128, в соответствии с http://www.w3.org/TR/html4/sgml/entities.html

+0

Ницца. Он не использует «html-версии» кодировок (например: «á» будет «& aacute;» вместо «á»), но поскольку числовые работают даже в IE7, я думаю, мне не нужно беспокоиться , Благодарю. – nonzaprej

27

Для тех, кто использует 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); 
Смежные вопросы