Как декодировать HTML-сущности с помощью jQuery? - PullRequest
321 голосов
/ 18 июля 2009

Как использовать jQuery для декодирования HTML-объектов в строку?

Ответы [ 19 ]

431 голосов
/ 10 марта 2010

Примечание по безопасности: использование этого ответа (сохранено в его первоначальном виде ниже) может привести к уязвимости XSS в вашем приложении. Вы не должны использовать этот ответ. Прочитайте ответ lucascaro для объяснения уязвимостей в этом ответе и используйте подход из этого ответа или Отметьте ответ Амери * вместо этого.

Собственно, попробуйте

var decoded = $("<div/>").html(encodedStr).text();
195 голосов
/ 08 сентября 2009

без всяких jQuery:

function decodeEntities(encodedString) {
  var textArea = document.createElement('textarea');
  textArea.innerHTML = encodedString;
  return textArea.value;
}

console.log(decodeEntities('1 &amp; 2')); // '1 & 2'

Это работает аналогично принятому ответу , но безопасно для использования с ненадежным пользовательским вводом.


Проблемы безопасности в аналогичных подходах

Как отметил Майк Самуэль , выполнение этого с <div> вместо <textarea> с ненадежным пользовательским вводом является уязвимостью XSS, даже если <div> никогда не добавляется в DOM:

function decodeEntities(encodedString) {
  var div = document.createElement('div');
  div.innerHTML = encodedString;
  return div.textContent;
}

// Shows an alert
decodeEntities('<img src="nonexistent_image" onerror="alert(1337)">')

Однако эта атака невозможна против <textarea>, поскольку нет элементов HTML, для которых разрешено содержимое <textarea>. Следовательно, любые HTML-теги, все еще присутствующие в «кодированной» строке, будут автоматически кодироваться сущностью браузером.

function decodeEntities(encodedString) {
    var textArea = document.createElement('textarea');
    textArea.innerHTML = encodedString;
    return textArea.value;
}

// Safe, and returns the correct answer
console.log(decodeEntities('<img src="nonexistent_image" onerror="alert(1337)">'))

Предупреждение : Делать это с помощью методов jQuery .html() и .val() вместо использования .innerHTML и .value также небезопасен * для некоторых версий jQuery, даже при использовании textarea. Это связано с тем, что более старые версии jQuery сознательно и явно оценивали сценарии , содержащиеся в строке, переданной в .html(). Следовательно, такой код показывает предупреждение в jQuery 1.8:

//<!-- CDATA
// Shows alert
$("<textarea>")
.html("<script>alert(1337);</script>")
.text();

//-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>

* Спасибо Эру Пенкману за обнаружение этой уязвимости.

78 голосов
/ 18 октября 2012

Как сказал Майк Сэмюэл, не используйте jQuery.html (). Text () для декодирования html-объектов, поскольку это небезопасно.

Вместо этого используйте шаблонизатор, например Mustache.js или decodeEntities из комментария @ VyvIT.

Underscore.js Библиотека утилитарных поясов поставляется с методами escape и unescape, но они небезопасны для ввода пользователем:

_. Экранировать (строка)

_. Экранирования в (строка)

28 голосов
/ 18 июля 2009

Я думаю, вы путаете текст и методы HTML. Посмотрите на этот пример, если вы используете внутренний HTML-код элемента в качестве текста, вы получите декодированные HTML-теги (вторая кнопка). Но если вы используете их как HTML, вы получите представление в формате HTML (первая кнопка).

<div id="myDiv">
    here is a <b>HTML</b> content.
</div>
<br />
<input value="Write as HTML" type="button" onclick="javascript:$('#resultDiv').html($('#myDiv').html());" />
&nbsp;&nbsp;
<input value="Write as Text" type="button" onclick="javascript:$('#resultDiv').text($('#myDiv').html());" />
<br /><br />
<div id="resultDiv">
    Results here !
</div>

Первая кнопка пишет: здесь есть HTML контент.

Вторая кнопка пишет: здесь есть содержимое HTML .

Кстати, вы можете увидеть плагин, который я нашел в плагин jQuery - HTML декодировать и кодировать , который кодирует и декодирует строки HTML.

26 голосов
/ 10 мая 2012

Вопрос ограничен «с помощью jQuery», но некоторым может помочь узнать, что приведенный в лучшем ответе код jQuery выполняет следующие действия ниже ... это работает с jQuery или без него:

function decodeEntities(input) {
  var y = document.createElement('textarea');
  y.innerHTML = input;
  return y.value;
}
17 голосов
/ 11 мая 2014

Вы можете использовать библиотеку he , доступную из https://github.com/mathiasbynens/he

Пример:

console.log(he.decode("J&#246;rg &amp J&#xFC;rgen rocked to &amp; fro "));
// Logs "Jörg & Jürgen rocked to & fro"

Я обратился к автору библиотеки с вопросом о том, была ли какая-либо причина использовать эту библиотеку в клиентском коде в пользу взлома <textarea>, предоставленного в других ответах здесь и в другом месте. Он представил несколько возможных обоснований:

  • Если вы используете серверный узел node.js, использование библиотеки для кодирования / декодирования HTML дает вам единственное решение, которое работает как на стороне клиента, так и на стороне сервера.

  • В некоторых алгоритмах декодирования объектов в некоторых браузерах есть ошибки или отсутствует поддержка некоторых именованных ссылок на символы . Например, Internet Explorer будет правильно декодировать и отображать неразрывные пробелы (&nbsp;), но сообщать о них как об обычных пробелах, а не неразрывных через свойство innerText элемента DOM, ломая хак <textarea> (хотя только незначительным образом). Кроме того, IE 8 и 9 просто не поддерживают каких-либо новых ссылок на именованные символы, добавленных в HTML 5. Автор he также размещает тест поддержки ссылок на именованные символы в http://mathias.html5.org/tests/html/named-character-references/. В IE 8 сообщается более тысячи ошибок.

    Если вы хотите быть изолированным от ошибок браузера, связанных с декодированием сущностей и / или иметь возможность обрабатывать полный диапазон именованных ссылок на символы, вы не можете избежать хака <textarea>; вам понадобится библиотека вроде he .

  • Он просто чертовски хорош, чувствует, что делать это таким образом менее хакерски.

17 голосов
/ 22 сентября 2014

закодировать:

$("<textarea/>").html('<a>').html();      // return '&lt;a&gt'

расшифровывает:

$("<textarea/>").html('&lt;a&gt').val()   // return '<a>'
4 голосов
/ 08 сентября 2009

Используйте

myString = myString.replace( /\&amp;/g, '&' );

Проще всего сделать это на стороне сервера, потому что, очевидно, в JavaScript нет нативной библиотеки для обработки сущностей, и я не нашел ничего в верхней части результатов поиска для различных сред, расширяющих JavaScript.

Выполните поиск «JavaScript HTML-сущностей», и вы можете найти несколько библиотек именно для этой цели, но, вероятно, все они будут построены на основе вышеуказанной логики - заменить сущность на сущность.

1 голос
/ 01 января 2013

Вы должны сделать пользовательскую функцию для html-сущностей:

function htmlEntities(str) {
return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g,'&gt;').replace(/"/g, '&quot;');
}
0 голосов
/ 30 марта 2016

Вот еще одна проблема: Экранированная строка не выглядит читаемой при назначении входного значения

var string = _.escape("<img src=fake onerror=alert('boo!')>");
$('input').val(string);

Пример: https://jsfiddle.net/kjpdwmqa/3/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...