Чи можу я уникнути спеціальних символів html у JavaScript?


202

Я хочу вивести текст у HTML за допомогою функції javascript. Як я можу уникнути спеціальних символів html у JS? Чи є API?


11
Це не дублікат, оскільки це питання не задає питання про jQuery. Мене цікавить лише цей, оскільки я не використовую jQuery ...
lvella

Відповіді:


331
function escapeHtml(unsafe) {
    return unsafe
         .replace(/&/g, "&")
         .replace(/</g, "&lt;")
         .replace(/>/g, "&gt;")
         .replace(/"/g, "&quot;")
         .replace(/'/g, "&#039;");
 }

11
Чому "& # 039;" а не "& apos;" ?
sereda


2
Я вважаю, що регулярні вирази в replace()дзвінках непотрібні. Звичайні старі односимвольні рядки могли би зробити так само добре.
jamix

22
@jamix Ви не можете зробити глобальну заміну сирими рядками, тоді як сучасні браузерні двигуни досить добре оптимізують просте регулярне вираження.
bjornd

5
чи є стандартний API чи це єдиний спосіб?
Суніл Гарг

57

function escapeHtml(html){
  var text = document.createTextNode(html);
  var p = document.createElement('p');
  p.appendChild(text);
  return p.innerHTML;
}

// Escape while typing & print result
document.querySelector('input').addEventListener('input', e => {
  console.clear();
  console.log( escapeHtml(e.target.value) );
});
<input style='width:90%; padding:6px;' placeholder='&lt;b&gt;cool&lt;/b&gt;'>


Працюю тут, але не працює для мене офлайн у веб-переглядачі

47

Ви можете використовувати .text()функцію jQuery .

Наприклад:

http://jsfiddle.net/9H6Ch/

З документації jQuery щодо .text()функції:

Нам потрібно пам’ятати, що цей метод уникає рядка, наданого в міру необхідності, щоб він правильно відображався в HTML. Для цього він викликає метод DOM .createTextNode (), не інтерпретує рядок як HTML.

Попередні версії документації jQuery сформулювали це так ( наголос додано ):

Нам потрібно пам’ятати, що цей метод уникає рядка, наданого в міру необхідності, щоб він правильно відображався в HTML. Для цього він викликає метод DOM .createTextNode (), який замінює спеціальні символи їхніми еквівалентами сутності HTML (наприклад, <lt; for <).


3
Ви навіть можете використовувати його на новому елементі, якщо ви просто хочете конвертувати так: const str = "foo<>'\"&"; $('<div>').text(str).html()урожайfoo&lt;&gt;'"&amp;
amoebe

28

Я думаю, що я знайшов правильний спосіб це зробити ...

// Create a DOM Text node:
var text_node = document.createTextNode(unescaped_text);

// Get the HTML element where you want to insert the text into:
var elem = document.getElementById('msg_span');

// Optional: clear its old contents
//elem.innerHTML = '';

// Append the text node into it:
elem.appendChild(text_node);

Сьогодні я дізнався щось нове про HTML. w3schools.com/jsref/met_document_createtextnode.asp .
Sellorio

1
Зауважте, що вміст текстового вузла не уникнути, якщо ви спробуєте отримати доступ до нього так:document.createTextNode("<script>alert('Attack!')</script>").textContent
maechler

Це правильний спосіб, якщо все, що ви робите, це налаштування тексту. Це також textContent, але, очевидно, він недостатньо підтримується. Однак це не спрацює, якщо ви створюєте рядок з деяких частин тексту деяким html, тоді вам потрібно все-таки вийти.
jgmjgm


21

Це, безумовно, найшвидший спосіб, коли я це бачив. Плюс - це все без додавання, видалення чи зміни елементів на сторінці.

function escapeHTML(unsafeText) {
    let div = document.createElement('div');
    div.innerText = unsafeText;
    return div.innerHTML;
}

7
Попередження: це не уникає лапок, тому ви не можете використовувати вихідні значення атрибутів у HTML-коді. Наприклад, ви var divCode = '<div data-title="' + escapeHTML('Jerry "Bull" Winston') + '">Div content</div>'отримаєте недійсний HTML!
izogfif

17

Цікаво було знайти краще рішення:

var escapeHTML = function(unsafe) {
  return unsafe.replace(/[&<"']/g, function(m) {
    switch (m) {
      case '&':
        return '&amp;';
      case '<':
        return '&lt;';
      case '"':
        return '&quot;';
      default:
        return '&#039;';
    }
  });
};

Я не розбираю, >тому що це не порушує XML / HTML-код в результаті.

Ось орієнтири: http://jsperf.com/regexpairs Також я створив універсальну escapeфункцію: http://jsperf.com/regexpairs2


1
Цікаво побачити, що використання перемикача значно швидше, ніж карта. Я цього не очікував! Дякую, що поділились!
Пітер Т.

Є багато набагато більше символів unicode, ніж ви могли кодувати та враховувати. Я б зовсім не рекомендував цей ручний метод.
vsync

Чому б взагалі уникнути багатобайтових символів? Просто використовуйте UTF-8 скрізь.
Неоніт

4
Пропуск> може потенційно зламати код. Ви повинні мати на увазі, що всередині <> також знаходиться html. У такому випадку пропуск> порушиться. Якщо ви тільки рятуєтесь між тегами, вам, ймовірно, потрібен лише втечі <і &.
jgmjgm

8

Найбільш стислий та найефективніший спосіб відображення некодованого тексту - це використання textContentвластивостей.

Швидше, ніж використання innerHTML. І це без урахування втечі накладних витрат.

document.body.textContent = 'a <b> c </b>';


@ZzZombo, цілком нормально, що він не працює з тегами стилів та сценаріїв. Коли ви додаєте вміст до них, ви додаєте код , а не текст , використовуйте innerHTML в цьому випадку. Більше того, вам не потрібно уникати цього, це два спеціальні теги, які не розбираються як HTML. Під час розбору їх вміст трактується як текст, поки не </буде виконано завершальну послідовність .
користувач

6

DOM Elements підтримують перетворення тексту в HTML шляхом присвоєння innerText . innerText не є функцією, але присвоєння їй працює так, як ніби уникнути тексту.

document.querySelectorAll('#id')[0].innerText = 'unsafe " String >><>';

1
Принаймні, в Chrome, призначаючи багаторядковий текст, додаються <br>елементи замість нових рядків, які можуть порушити певні елементи, наприклад, стилі чи сценарії. createTextNodeЧи не схильний до цієї проблеми.
ZzZombo

1
innerTextмає деякі проблеми зі спадщиною / специфікою. Краще використовувати textContent.
Рой Тінкер

3

Ви можете кодувати кожен символ у рядку:

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}

Або просто націліть на головних персонажів, які турбуються про (&, неполадки, <,>, "та"), наприклад:

function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}

test.value=encode('How to encode\nonly html tags &<>\'" nice & fast!');

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<textarea id=test rows="9" cols="55">&#119;&#119;&#119;&#46;&#87;&#72;&#65;&#75;&#46;&#99;&#111;&#109;</textarea>


Написати власну функцію втечі, як правило, погана ідея. Інші відповіді в цьому плані кращі.
jannis

2

Однолінійний (для ES6 +):

var escapeHtml = s => (s + '').replace(/[&<>"']/g, m => ({
    '&': '&amp;', '<': '&lt;', '>': '&gt;',
    '"': '&quot;', "'": '&#39;'
})[m]);

Для старих версій:

function escapeHtml(s) {
    return (s + '').replace(/[&<>"']/g, function (m) {
        return ({
            '&': '&amp;', '<': '&lt;', '>': '&gt;',
            '"': '&quot;', "'": '&#39;'
        })[m];
    });
}

0

У цьому питанні зіткнулися під час створення структури DOM. Це питання допомогло мені вирішити. Я хотів використовувати подвійний шеврон як роздільник шляху, але додавання нового текстового вузла безпосередньо призвело до відображення униклого коду символів, а не до самого символу:

var _div = document.createElement('div');
var _separator = document.createTextNode('&raquo;');
//_div.appendChild(_separator); /* this resulted in '&raquo;' being displayed */
_div.innerHTML = _separator.textContent; /* this was key */

0

Якщо ви вже використовуєте модулі у своєму додатку, ви можете використовувати модуль escape-html .

import escapeHtml from 'escape-html';
const unsafeString = '<script>alert("XSS");</script>';
const safeString = escapeHtml(unsafeString);


-4

Я придумав таке рішення.

Припустимо, що ми хочемо додати трохи елемента до HTML з небезпечними даними користувача або бази даних.

var unsafe = 'some unsafe data like <script>alert("oops");</script> here';

var html = '';
html += '<div>';
html += '<p>' + unsafe + '</p>';
html += '</div>';

element.html(html);

Це небезпечно від атак XSS. Тепер додайте це.

$(document.createElement('div')).html(unsafe).text();

Так воно і є

var unsafe = 'some unsafe data like <script>alert("oops");</script> here';

var html = '';
html += '<div>';
html += '<p>' + $(document.createElement('div')).html(unsafe).text(); + '</p>';
html += '</div>';

element.html(html);

Мені це набагато простіше, ніж використовувати, .replace()і він видалиться !!! всі можливі теги html (я сподіваюся).


ця небезпечна ідея, вона розбирає небезпечний рядок HTML як HTML, якби елемент був приєднаний до DOM, він би виконав. використовувати замість .innerText.
текнопаул

Це не безпечно. Він перетворюється &lt;script&gt;на <script>.
fgb
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.