Как декодировать HTML-сущности с помощью jQuery?

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

20 ответов

Решение

Примечание по безопасности: использование этого ответа (сохранено в его первоначальном виде ниже) может привести к уязвимости XSS в вашем приложении. Вы не должны использовать этот ответ. Прочитайте ответ Люкаскаро, чтобы объяснить уязвимости в этом ответе, и вместо этого используйте подход из этого ответа или ответа Марка Эмери.

На самом деле, попробуйте

var decoded = $("<div/>").html(encodedStr).text();

Без каких-либо 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's .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>

* Спасибо roo2 за roo2 этой уязвимости.

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

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

Библиотека утилитарных поясов http://underscorejs.org/ поставляется с escape а также unescape методы, но они не безопасны для ввода пользователем:

_.escape (строка)

_.unescape (строка)

Я думаю, что вы путаете текст и методы 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-строки.

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

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

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

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

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

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

Вы можете использовать библиотеку 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> взломать в других ответах здесь и в других местах. Он представил несколько возможных оправданий:

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

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

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

  • Он просто чертовски хорош, чувствует себя так, как будто не так хакерски.

Попробуй это:

var htmlEntities = "&lt;script&gt;alert('hello');&lt;/script&gt;";
var htmlDecode =$.parseHTML(htmlEntities)[0]['wholeText'];
console.log(htmlDecode);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

parseHTML - это функция из библиотеки Jquery, которая возвращает массив, содержащий некоторые сведения о данной строке.

в некоторых случаях значение String велико, поэтому функция будет разделять содержимое на множество индексов.

и чтобы получить все данные индексов, вы должны перейти к любому индексу, а затем получить доступ к индексу, называемому "wholeText".

Я выбрал индекс 0, потому что он будет работать во всех случаях (маленькая строка или большая строка).

Использование

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

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

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

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

function htmlEntities(str) {
return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g,'&gt;').replace(/"/g, '&quot;');
}

Расширить класс String:

String::decode = ->
  $('<textarea />').html(this).text()

и использовать в качестве метода:

"&lt;img src='myimage.jpg'&gt;".decode()

Предположим, у вас ниже строки.

Наши роскошные каюты теплые, уютные и удобный

var str = $("p").text(); // get the text from <p> tag
$('p').html(str).text();  // Now,decode html entities in your variable i.e 

ул и назначить обратно

тег.

вот и все.

Для решения этой проблемы вам не нужен jQuery, поскольку он создает небольшие накладные расходы и зависимость.

Я знаю, что здесь есть много хороших ответов, но, поскольку я реализовал немного другой подход, я решил поделиться.

Этот код представляет собой совершенно безопасный подход с точки зрения безопасности, поскольку обработчик экранирования зависит от браузера, а не от функции. Таким образом, если в будущем будет обнаружена новая уязвимость, это решение будет покрыто.

      const decodeHTMLEntities = text => {
    // Create a new element or use one from cache, to save some element creation overhead
    const el = decodeHTMLEntities.__cache_data_element 
             = decodeHTMLEntities.__cache_data_element 
               || document.createElement('div');
    
    const enc = text
        // Prevent any mixup of existing pattern in text
        .replace(/⪪/g, '⪪#')
        // Encode entities in special format. This will prevent native element encoder to replace any amp characters
        .replace(/&([a-z1-8]{2,31}|#x[0-9a-f]+|#\d+);/gi, '⪪$1⪫');

    // Encode any HTML tags in the text to prevent script injection
    el.textContent = enc;

    // Decode entities from special format, back to their original HTML entities format
    el.innerHTML = el.innerHTML
        .replace(/⪪([a-z1-8]{2,31}|#x[0-9a-f]+|#\d+)⪫/gi, '&$1;')
        .replace(/#⪫/g, '⪫');
   
    // Get the decoded HTML entities
    const dec = el.textContent;
    
    // Clear the element content, in order to preserve a bit of memory (it is just the text may be pretty big)
    el.textContent = '';

    return dec;
}

// Example
console.log(decodeHTMLEntities("<script>alert('&awconint;&CounterClockwiseContourIntegral;&#x02233;&#8755;⪪#x02233⪫');</script>"));
// Prints: <script>alert('∳∳∳∳⪪##x02233⪫');</script>

Кстати, я решил использовать символы а также , потому что они используются редко, поэтому вероятность влияния на производительность путем их сопоставления значительно ниже.

Для пользователей ExtJS, если у вас уже есть закодированная строка, например, когда возвращаемое значение библиотечной функции является содержимым innerHTML, рассмотрите эту функцию ExtJS:

Ext.util.Format.htmlDecode(innerHtmlContent)

Мне просто нужно было использовать символ сущности HTML (⇓) в качестве значения кнопки HTML. HTML-код выглядит хорошо с самого начала в браузере:

<input type="button" value="Embed & Share  &dArr;" id="share_button" />

Теперь я добавил переключатель, который также должен отображать характер. Это мое решение

$("#share_button").toggle(
    function(){
        $("#share").slideDown();
        $(this).attr("value", "Embed & Share " + $("<div>").html("&uArr;").text());
    }

На дисплее снова отобразится ⇓. Я надеюсь, что это может кому-то помочь.

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

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

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

Кроме того, есть также библиотека для этого..

здесь, https://cdnjs.com/libraries/he

npm install he                 //using node.js

<script src="js/he.js"></script>  //or from your javascript directory

Использование заключается в следующем...

//to encode text 
he.encode('© Ande & Nonso® Company LImited 2018');  

//to decode the 
he.decode('&copy; Ande &amp; Nonso&reg; Company Limited 2018');

веселит.

Самый простой способ - установить селектор класса на ваши элементы, а затем использовать следующий код:

$(function(){
    $('.classSelector').each(function(a, b){
        $(b).html($(b).text());
    });
});

Больше ничего не нужно!

У меня была эта проблема, и я нашел это ясное решение, и оно отлично работает.

Я думаю, что это полная противоположность выбранному решению.

var decoded = $("<div/>").text(encodedStr).html();

Чтобы декодировать HTML-сущности с помощью jQuery, просто используйте эту функцию:

function html_entity_decode(txt){
    var randomID = Math.floor((Math.random()*100000)+1);
    $('body').append('<div id="random'+randomID+'"></div>');
    $('#random'+randomID).html(txt);
    var entity_decoded = $('#random'+randomID).html();
    $('#random'+randomID).remove();
    return entity_decoded;
}

Как пользоваться:

Javascript:

var txtEncoded = "&aacute; &eacute; &iacute; &oacute; &uacute;";
$('#some-id').val(html_entity_decode(txtEncoded));

HTML:

<input id="some-id" type="text" />
Другие вопросы по тегам