Как декодировать 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 & 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>
Как сказал Майк Самуэль, не используйте jQuery.html(). Text() для декодирования html-объектов, поскольку это небезопасно.
Вместо этого используйте средство визуализации шаблонов, такое как Mustache.js или decodeEntities из комментария @VyvIT.
Библиотека утилитарных поясов http://underscorejs.org/ поставляется с 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());" />
<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 '<a>'
расшифровывает:
$("<textarea/>").html('<a>').val() // return '<a>'
Вы можете использовать библиотеку he, доступную по https://github.com/mathiasbynens/he
Пример:
console.log(he.decode("Jörg & Jürgen rocked to & fro "));
// Logs "Jörg & Jürgen rocked to & fro"
Я обратился к автору библиотеки с вопросом о том, была ли какая-либо причина использовать эту библиотеку в клиентском коде в пользу <textarea>
взломать в других ответах здесь и в других местах. Он представил несколько возможных оправданий:
Если вы используете server.js на стороне сервера, использование библиотеки для кодирования / декодирования HTML дает вам единственное решение, которое работает как на стороне клиента, так и на стороне сервера.
Алгоритмы декодирования сущностей некоторых браузеров содержат ошибки или не поддерживают некоторые ссылки на именованные символы. Например, Internet Explorer будет декодировать и обрабатывать неразрывные пробелы (
) правильно, но сообщать о них как об обычных пробелах вместо неразрывных через элемент DOMinnerText
собственность, нарушая<textarea>
взломать (правда, только незначительным образом). Кроме того, IE 8 и 9 просто не поддерживают ни одну из новых ссылок на именованные символы, добавленных в HTML 5. Автор также проводит тест поддержки ссылок на именованные символы на http://mathias.html5.org/tests/html/named-character-references/. В IE 8 сообщается более тысячи ошибок.Если вы хотите быть изолированным от ошибок браузера, связанных с декодированием сущностей, и / или иметь возможность обрабатывать полный диапазон именованных ссылок на символы, вам не сойдет с рук
<textarea>
взломать; Вам понадобится библиотека, как он.Он просто чертовски хорош, чувствует себя так, как будто не так хакерски.
Попробуй это:
var htmlEntities = "<script>alert('hello');</script>";
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( /\&/g, '&' );
Проще всего это сделать на стороне сервера, поскольку, очевидно, в JavaScript нет нативной библиотеки для обработки сущностей, и я не нашел ничего в верхней части результатов поиска для различных сред, расширяющих JavaScript.
Выполните поиск "JavaScript HTML-сущностей", и вы можете найти несколько библиотек именно для этой цели, но, вероятно, все они будут построены на основе вышеуказанной логики - заменить сущность на сущность.
Вы должны сделать пользовательскую функцию для HTML-объектов:
function htmlEntities(str) {
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g,'>').replace(/"/g, '"');
}
Расширить класс String:
String::decode = ->
$('<textarea />').html(this).text()
и использовать в качестве метода:
"<img src='myimage.jpg'>".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('∳∳∳∳⪪#x02233⪫');</script>"));
// Prints: <script>alert('∳∳∳∳⪪##x02233⪫');</script>
Кстати, я решил использовать символы
⪪
а также
⪫
, потому что они используются редко, поэтому вероятность влияния на производительность путем их сопоставления значительно ниже.
Для пользователей ExtJS, если у вас уже есть закодированная строка, например, когда возвращаемое значение библиотечной функции является содержимым innerHTML, рассмотрите эту функцию ExtJS:
Ext.util.Format.htmlDecode(innerHtmlContent)
Мне просто нужно было использовать символ сущности HTML (⇓) в качестве значения кнопки HTML. HTML-код выглядит хорошо с самого начала в браузере:
<input type="button" value="Embed & Share ⇓" id="share_button" />
Теперь я добавил переключатель, который также должен отображать характер. Это мое решение
$("#share_button").toggle(
function(){
$("#share").slideDown();
$(this).attr("value", "Embed & Share " + $("<div>").html("⇑").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('© Ande & Nonso® 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 = "á é í ó ú";
$('#some-id').val(html_entity_decode(txtEncoded));
HTML:
<input id="some-id" type="text" />