Уникнення рядків HTML за допомогою jQuery


609

Хтось знає про простий спосіб уникнути HTML із рядків у jQuery ? Мені потрібно вміти пропустити довільну рядок і правильно її вимкнути для відображення на HTML-сторінці (запобігаючи атакам JavaScript / HTML-ін'єкції). Я впевнений, що можна розширити jQuery для цього, але наразі я не знаю достатньо про рамки для цього.


Також дивіться perf
Крістоф Руссі

Відповіді:


445

Оскільки ви використовуєте jQuery , ви можете просто встановити textвластивість елемента :

// before:
// <div class="someClass">text</div>
var someHtmlString = "<script>alert('hi!');</script>";

// set a DIV's text:
$("div.someClass").text(someHtmlString);
// after: 
// <div class="someClass">&lt;script&gt;alert('hi!');&lt;/script&gt;</div>

// get the text in a string:
var escaped = $("<div>").text(someHtmlString).html();
// value: 
// &lt;script&gt;alert('hi!');&lt;/script&gt;

57
Ви пропустили пункт про те, що вам потрібно отримати доступ до $ ("div.someClass").
Мортен Крістіансен

16
Це не безпечно для веб-переглядача, якщо у вашій рядку є пробіли та \ n \ r \ t символи
nivcaner

20
@travis Це задокументовано на веб-сайті jQuery: "Через зміни в HTML-аналізаторах у різних браузерах текст, що повертається, може відрізнятися в нових рядках та іншому пробілі". api.jquery.com/text
geofflee

3
@mklement , якщо ви вже використовуєте це рішення, ви не будете мати ніяких проблем з цим робити що - щось на кшталт: $(element2).attr("some-attr", $(element1).html());Дивіться цей приклад: jsbin.com/atibig/1/edit
Тревіс

16
Це НЕ уникає цитат і подвійних цитат, що погано! wonko.com/post/html-escaping
Lior

601

Також є рішення від mustache.js

var entityMap = {
  '&': '&amp;',
  '<': '&lt;',
  '>': '&gt;',
  '"': '&quot;',
  "'": '&#39;',
  '/': '&#x2F;',
  '`': '&#x60;',
  '=': '&#x3D;'
};

function escapeHtml (string) {
  return String(string).replace(/[&<>"'`=\/]/g, function (s) {
    return entityMap[s];
  });
}

7
Зауважте, що, як цікаво, 'відображається на об'єкт із десятковою формою, тоді як він /використовує шістнадцятковий формат.
mklement0

43
Це має бути прийнятою відповіддю - це просто, ефективно, не вимагає залежностей і робить саме те, що призначено, без незрозумілих злому.
lorefnon

6
що керівництво по перетворенню \nв <br>?
amwinter

2
Ось оновлене посилання на джерело: github.com/janl/mustache.js/blob/…
mjackson

8
@amwinter, я розширив скрипт вище, додавши "\ n": '<br>' до мапи сутності та оновив регулярне вираження до / [& <> "'\ /] | [\ n] / g
walv

182
$('<div/>').text('This is fun & stuff').html(); // "This is fun &amp; stuff"

Джерело: http://debuggable.com/posts/encode-html-entities-with-jquery:280f4dd6-13cc-4ce9-8071-4710cbdd56cb


11
Як було сказано у відповіді вище, це рішення не гарантує збереження пробілу.
геофле

47
Слід зазначити, що це не допомагає уникнути одинарних чи подвійних цитат. якщо ви плануєте ввести значення в атрибут HTML, це може бути проблемою.
Кіп

6
@Kip: @travis виявив, що attr()метод jQuery (як мінімум, 1.8.3) робить власне кодування, так що невкодовані рядки можуть передаватися безпосередньо ; наприклад:$('<div/>').attr('test-attr', '\'Tis "fun" & stuff')[0].outerHTML
mklement0

1
@tarekahf Це дивно. Яку версію jQuery ви використовуєте? Чи працює приклад коду, якщо ви копіюєте і вставляєте його дослівно? Чудово працює з останньою версією jQuery (3.1.0) тут: jsbin.com/fazimigayo/1/edit?html,js,console,output (і вона також повинна працювати на всіх попередніх версіях)
Henrik N

1
@tarekahf $('<div/>')створює новий divелемент, який не приєднаний до DOM. Таким чином, це не змінить жодних існуючих елементів. Це трохи заплутано, як jQuery використовує ту саму $()функцію як для пошуку елементів ( $('div')), так і для їх створення, та ще для кількох речей, окрім… :)
Henrik N

61

Якщо ви врятуєтесь за HTML, я можу подумати про це лише три:

html.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");

В залежності від вашого випадку використання, ви можете також повинні робити речі , як "до &quot;. Якщо список отримав достатньо великий, я б просто використав масив:

var escaped = html;
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]]
for(var item in findReplace)
    escaped = escaped.replace(findReplace[item][0], findReplace[item][1]);

encodeURIComponent() буде уникати його лише для URL-адрес, а не для HTML.


13
Цей регулярний вираз дасть дивні результати, якщо HTML, про який йде мова, вже уникнув сутності. Наприклад, втеча від "Tom & amp; Jerry" призведе до "Tom & amp; Jerry"
Райан

12
Будь ласка, використовуйте varдля декларації на itemмісцевому рівні; так чи інакше, не використовуйте for … inцикл під час циклу через масив! Використовуйте forзамість цього звичайну петлю. О, і це encodeURIComponent, ні escapeURIComponent.
Марсель Корпель

3
Якщо ви працюєте з атрибутами тегів, вам також знадобиться відмовитися від лапок та / або подвійних лапок. Документація PHP для htmlspecialchars містить корисний список перетворень, які він здійснює. php.net/htmlspecialchars
geofflee

4
Просто свого роду нагадування для нових людей, не використовуйте це , якщо ви збираєтеся мати окрім англійської символи де - то на вашому сайті ... Очевидно , що це не буде робити з символів з акцентами , як «E»: &eacute; Ось список об’єктів html, для довідки: w3schools.com/tags/ref_entities.asp
LoganWolfer

11
@Ryan: Хоча варто зазначити, що це рішення не обробляє вже закодовані рядки правильно, також нічого не варто, що те саме стосується більшості - можливо, всіх - рішень на цій сторінці.
mklement0

37

Досить просто використовувати підкреслення:

_.escape(string) 

Underscore - це бібліотека утиліт, яка надає безліч функцій, які не дає нативний js. Також є lodash, який є тим самим API, що і підкреслення, але він був переписаний, щоб бути більш ефективним.


36

Я написав маленьку маленьку функцію, яка це робить. Він тільки тікає ", &, <і >(але , як правило, це все , що вам потрібно в будь-якому випадку). Це трохи елегантніше, ніж запропоновані раніше рішення, оскільки для їх перетворення використовується лише одне .replace() . ( EDIT 2: Зменшення складності коду робить функцію ще меншою та акуратнішою, якщо вам цікаво оригінальний код, див. Кінець цієї відповіді.)

function escapeHtml(text) {
    'use strict';
    return text.replace(/[\"&<>]/g, function (a) {
        return { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' }[a];
    });
}

Це звичайний Javascript, не використовується jQuery.

Втеча /і 'теж

Редагувати у відповідь на коментар mklement .

Вищевказану функцію можна легко розширити, включаючи будь-який символ. Щоб вказати більше символів для втечі, просто вставляйте їх як у клас символів у регулярному виразі (тобто всередині /[...]/g), так і як запис у chrоб’єкті. ( EDIT 2: Скорочуйте цю функцію також аналогічно.)

function escapeHtml(text) {
    'use strict';
    return text.replace(/[\"&'\/<>]/g, function (a) {
        return {
            '"': '&quot;', '&': '&amp;', "'": '&#39;',
            '/': '&#47;',  '<': '&lt;',  '>': '&gt;'
        }[a];
    });
}

Зверніть увагу на вищезазначене використання &#39;апострофа (символьна сутність, &apos;можливо, була використана натомість - вона визначена в XML, але спочатку не була включена в специфікацію HTML, тому може не підтримуватися всіма браузерами. Див.: Стаття Вікіпедії про кодування символів HTML ). Я також пригадую, що десь читав, що використання десяткових сутностей більш широко підтримується, ніж використання шістнадцяткових, але я не можу зараз знайти джерело для цього. (І там не може бути багато браузерів, які не підтримують шістнадцяткову сутність.)

Примітка. Додавання /та 'перелік символів, що увійшли, не є таким корисним, оскільки вони не мають особливого значення в HTML і не потребують цього уникати.

Оригінальна escapeHtmlфункція

EDIT 2: Оригінальна функція використовувала змінну ( chr) для зберігання об'єкта, необхідного для .replace()зворотного виклику. Ця змінна також потребувала додаткової анонімної функції, щоб розширити її, зробивши функцію (без потреби) трохи більшою і складною.

var escapeHtml = (function () {
    'use strict';
    var chr = { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' };
    return function (text) {
        return text.replace(/[\"&<>]/g, function (a) { return chr[a]; });
    };
}());

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


Дякую, що знайшли час, @Zrajm. Хороший момент про те, що не потрібно бігти; будь-яка ідея, чому і те, mustache.jsі underscore.jsробити це? Говорячи про останній: вона визнає тільки числові об'єкти (що представляють 'і /«), в верхньому регістрі шестигранною форми , коли ип втечі. Таким чином, текст вирвався в mustache.js- який цікаво використовує суміш шістнадцяткових. та десяткових форматів - не буде правильно скасовано в underscore.js. Цікаво, як з цим справляються інші популярні бібліотеки.
mklement0

1
Нижня форма разі шестигранною найбільш підтримується форма, так що це (можливо) форма , що бібліотеки повинні бути перетворені в . (Звичайно, обидві форми повинні працювати при перетворенні з .) - Апострофи 'мають якусь зарезервовану функцію в XML (і, таким чином, XHTML, я думаю?), Саме тому XML (але не HTML) має названу сутність &apos;. Я точно не знаю, чому саме та чому він "зарезервований". - Косові риси в URL-адресах є особливими, але це фактично не гарантує їх включення до HTML , що виходить (оскільки кодування URL - це зовсім інше).
zrajm

Re &apos;: правильно: безпечне використання тільки в XHTML ; прямо з уст джерела натовпу - моє наголос: "(...) читається відповідним процесором HTML , (...) використання" або спеціальних посилань на сутність може не підтримуватися (...) "- на практиці : сучасні браузери підтримують його навіть у HTML . Перезапис у шістнадцяткових цифрах (те саме джерело; моє наголос): "У документах XML х має бути малий регістр. [...] Hhhh може змішувати великі та малі регістри, хоча великі регістри - це звичайний стиль ." Залишає нас цікавитись, хто вирішив кодувати косої риси; можливо, справді просто плутанина між кодовим кодом URI та HTML?
mklement0

2
Підсумкові думки: здається, що кодування /не потрібно, але кодування 'все ще здається корисним для безпечного поводження з випадком, коли кодована рядок використовується як значення атрибута, укладене в одиничні лапки .
mklement0

Обидва вони повільні. Найшвидше рішення з двозначним запасом - це ряд замін, які передаються рядками замість функцій.
Адам Леггетт

34

Я розумію, як я спізнююсь на цю вечірку, але у мене дуже просте рішення, яке не потребує jQuery.

escaped = new Option(unescaped).innerHTML;

Редагувати: Цитата не уникає. Єдиний випадок, коли цитати потрібно уникати, якщо вміст буде вставлено в атрибут в HTML-рядку. Мені важко уявити випадок, коли це було б гарним дизайном.

Редагування 3: Для найшвидшого рішення перевірте відповідь вище від Сарама. Цей найкоротший.


Це не змінює котирування - принаймні зараз у Firefox 52.
getsetbro

1
Вихідні лапки є лише функціонально релевантними в атрибутах. Оскільки ми рятуємося, <і >уникнути цитат також немає користі, якщо тільки наміром створеного вмісту не перейти в атрибут.
Адам Леггетт

31

Ось чиста, чітка функція JavaScript. Текст, такий як "кілька <багато", перетвориться на "кілька & багато; багато".

function escapeHtmlEntities (str) {
  if (typeof jQuery !== 'undefined') {
    // Create an empty div to use as a container,
    // then put the raw text in and get the HTML
    // equivalent out.
    return jQuery('<div/>').text(str).html();
  }

  // No jQuery, so use string replace.
  return str
    .replace(/&/g, '&amp;')
    .replace(/>/g, '&gt;')
    .replace(/</g, '&lt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&apos;');
}

28

Після останніх тестів я можу рекомендувати швидкий і повністю крос - браузер , сумісний рідної JavaScript рішення (DOM):

function HTMLescape(html){
    return document.createElement('div')
        .appendChild(document.createTextNode(html))
        .parentNode
        .innerHTML
}

Якщо ви повторите це багато разів, ви можете зробити це за допомогою готових змінних:

//prepare variables
var DOMtext = document.createTextNode("test");
var DOMnative = document.createElement("span");
DOMnative.appendChild(DOMtext);

//main work for each case
function HTMLescape(html){
  DOMtext.nodeValue = html;
  return DOMnative.innerHTML
}

Подивіться на моє остаточне порівняння продуктивності ( питання про стек ).


2
Чи потрібно використовувати два вузли? Як щодо лише одного:var p = document.createElement('p'); p.textContent = html; return p.innerHTML;
Дана Даскалеску

2
@DanDascalescu: За даними MDN , textContentфункцію підтримують лише Chrome 1+, Firefox 2, IE9, Opera 9.64 та Safari 3 (останні два анотації "можливо раніше"). Таким чином, це порушило б заявку на "повністю сумісні між браузерами" ОП.
zb226

p.innerText = html; return p.innerHTML
Бекім Бакай

24

Спробуйте Underscore.string lib, він працює з jQuery.

_.str.escapeHTML('<div>Blah blah blah</div>')

вихід:

'&lt;div&gt;Blah blah blah&lt;/div&gt;'

20
Основна бібліотека підкреслення тепер має _.escape()корисну функцію.
codeape

15

Я покращив приклад mustache.js, додавши escapeHTML()метод до об’єкта рядка.

var __entityMap = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': '&quot;',
    "'": '&#39;',
    "/": '&#x2F;'
};

String.prototype.escapeHTML = function() {
    return String(this).replace(/[&<>"'\/]/g, function (s) {
        return __entityMap[s];
    });
}

Таким чином, він досить простий у використанні "Some <text>, more Text&Text".escapeHTML()


Корисно, але також я перейшов __entityMapу функцію локальної сфери. І завершив усе цеif (typeof String.prototype.escapeHTML !== 'function'){...}
FlameStorm

15

escape()і unescape()призначені для кодування / декодування рядків для URL-адрес, а не HTML.

Насправді я використовую такий фрагмент, щоб зробити трюк, який не потребує будь-яких фреймворків:

var escapedHtml = html.replace(/&/g, '&amp;')
                      .replace(/>/g, '&gt;')
                      .replace(/</g, '&lt;')
                      .replace(/"/g, '&quot;')
                      .replace(/'/g, '&apos;');

Якщо у вас буде "s, то вам потрібно додати принаймні 'і `` в бійку. Вони потрібні лише для даних тегів рядків всередині елементів у html. Для самих HTML-даних (зовнішні теги) потрібні лише перші 3.
Маріус

10

Якщо у вас є underscore.js, використовуйте _.escape(ефективніше, ніж метод jQuery, розміщений вище):

_.escape('Curly, Larry & Moe'); // returns: Curly, Larry &amp; Moe

5

Якщо ви рухаєтесь маршрутом маршрутизації, у прикладі tghw вище є помилка.

<!-- WON'T WORK -  item[0] is an index, not an item -->

var escaped = html; 
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g,"&gt;"], [/"/g,
"&quot;"]]

for(var item in findReplace) {
     escaped = escaped.replace(item[0], item[1]);   
}


<!-- WORKS - findReplace[item[]] correctly references contents -->

var escaped = html;
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]]

for(var item in findReplace) {
     escaped = escaped.replace(findReplace[item[0]], findReplace[item[1]]);
}

2
Я вважаю, що це має бути для (var item in findReplace) {escape = escapeped.replace (findReplace [item] [0], findReplace [item] [1]); }
Кріс Стівенс

5

Це приємний безпечний приклад ...

function escapeHtml(str) {
    if (typeof(str) == "string"){
        try{
            var newStr = "";
            var nextCode = 0;
            for (var i = 0;i < str.length;i++){
                nextCode = str.charCodeAt(i);
                if (nextCode > 0 && nextCode < 128){
                    newStr += "&#"+nextCode+";";
                }
                else{
                    newStr += "?";
                }
             }
             return newStr;
        }
        catch(err){
        }
    }
    else{
        return str;
    }
}

4
Які винятки ви там пригнічуєте?
Стефан Маєвський

3

Ви можете легко зробити це з ванільним js.

Просто додайте в текстовий вузол документ. Це перешкодить браузеру.

var escaped = document.createTextNode("<HTML TO/ESCAPE/>")
document.getElementById("[PARENT_NODE]").appendChild(escaped)

2
(function(undefined){
    var charsToReplace = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;'
    };

    var replaceReg = new RegExp("[" + Object.keys(charsToReplace).join("") + "]", "g");
    var replaceFn = function(tag){ return charsToReplace[tag] || tag; };

    var replaceRegF = function(replaceMap) {
        return (new RegExp("[" + Object.keys(charsToReplace).concat(Object.keys(replaceMap)).join("") + "]", "gi"));
    };
    var replaceFnF = function(replaceMap) {
        return function(tag){ return replaceMap[tag] || charsToReplace[tag] || tag; };
    };

    String.prototype.htmlEscape = function(replaceMap) {
        if (replaceMap === undefined) return this.replace(replaceReg, replaceFn);
        return this.replace(replaceRegF(replaceMap), replaceFnF(replaceMap));
    };
})();

Немає глобальних змінних, деяка оптимізація пам'яті. Використання:

"some<tag>and&symbol©".htmlEscape({'©': '&copy;'})

Результат:

"some&lt;tag&gt;and&amp;symbol&copy;"

2

2 простих методу, які не потребують жодної роботи

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

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)+";"})
}

var myString='Encode HTML entities!\n"Safe" escape <script></'+'script> & other tags!';

test.value=encode(myString);

testing.innerHTML=encode(myString);

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<p><b>What JavaScript Generated:</b></p>

<textarea id=test rows="3" cols="55"></textarea>

<p><b>What It Renders Too In HTML:</b></p>

<div id="testing">www.WHAK.com</div>


2

Простий приклад JavaScript:

function escapeHtml(text) {
    var div = document.createElement('div');
    div.innerText = text;
    return div.innerHTML;
}

escapeHtml("<script>alert('hi!');</script>")
// "&lt;script&gt;alert('hi!');&lt;/script&gt;"

3
Відповіді, що стосуються лише коду, відмовляються, оскільки вони не пояснюють, як вони вирішують проблему. Будь ласка, оновіть свою відповідь, щоб пояснити, як це покращується щодо інших прийнятих та обґрунтованих відповідей, на які це питання вже є. Крім того, цьому питанню 9 років, ваші зусилля будуть оцінені користувачами, які мають останні відповіді без відповіді. Будь ласка, перегляньте Як написати гарну відповідь .
FluffyKitten

1
@FluffyKitten - це надзвичайно нігтьова написана публікація в блозі про переваги та недоліки такої функції, яка докладно пояснює все, що ви хотіли б знати :) shebang.brandonmintern.com/…
db306

@ db306 Відповідь позначено як низьку якість, оскільки відповідь, що стосується лише коду, не відповідає керівництву щодо переповнення стека - див. Як написати хорошу відповідь . Мій коментар був доданий під час огляду, щоб пояснити, що потрібно для його вдосконалення, тобто відповідь потрібно оновити, щоб пояснити, що робить код і як він покращується в існуючих відповідях. Резюме від інших рецензентів, щоб підтвердити це. Додавання зовнішнього посилання до коментарів все ще не відповідає положенням SO. Натомість Ендрю потрібно включити відповідну інформацію безпосередньо у свою відповідь.
FluffyKitten

Зауважте, що закінчився термін дії торгової марки "Брендонмінтерн" і тепер припаркований. Нова адреса shebang - shebang.mintern.net/foolproof-html-escaping-in-javascript/.
Брендон

0
function htmlEscape(str) {
    var stringval="";
    $.each(str, function (i, element) {
        alert(element);
        stringval += element
            .replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(' ', '-')
            .replace('?', '-')
            .replace(':', '-')
            .replace('|', '-')
            .replace('.', '-');
    });
    alert(stringval);
    return String(stringval);
}

0
function htmlDecode(t){
   if (t) return $('<div />').html(t).text();
}

працює як шарм


текст видаляє html-теги, але $ ('<div />'). html (t) .html (); твори
Bass Jobsen

0

Ця відповідь надає методи jQuery і звичайні JS, але це найкоротше, не використовуючи DOM:

unescape(escape("It's > 20% less complicated this way."))

Рядок, що уникнув: It%27s%20%3E%2020%25%20less%20complicated%20this%20way.

Якщо місця, що втекли, турбують вас, спробуйте:

unescape(escape("It's > 20% less complicated this way.").replace(/%20/g, " "))

Рядок, що уникнув: It%27s %3E 20%25 less complicated this way.

На жаль, escape()функція застаріла в JavaScript версії 1.5 . encodeURI()або encodeURIComponent()є альтернативами, але вони ігнорують ', тому останній рядок коду перетвориться на такий:

decodeURI(encodeURI("It's > 20% less complicated this way.").replace(/%20/g, " ").replace("'", '%27'))

Усі основні браузери все ще підтримують короткий код, а враховуючи кількість старих веб-сайтів, я сумніваюся, що незабаром це зміниться.


Це для кодування URL-адрес. Питання стосувалося втечі HTML, що дуже відрізняється.
thelem

@thelem, не якщо рядки вбудовані в масиви JavaScript, вбудовані в HTML, але я погоджуюся, що мова йшла про звичайний HTML-код, щоб його можна було негайно відобразити як текст.
Cees Timmerman

0

ES6 один вкладиш для рішення з mustache.js

const escapeHTML = str => (str+'').replace(/[&<>"'`=\/]/g, s => ({'&': '&amp;','<': '&lt;','>': '&gt;','"': '&quot;',"'": '&#39;','/': '&#x2F;','`': '&#x60;','=': '&#x3D;'})[s]);

-2

Якщо ви зберігаєте цю інформацію в базі даних , її неправильне виведення HTML за допомогою сценарію на стороні клієнта , це слід зробити на сервері . В іншому випадку легко обійти ваш захист XSS.

Щоб зрозуміти мою думку, ось приклад з використанням однієї з відповідей:

Скажімо, ви використовуєте функцію escapeHtml, щоб уникнути Html від коментаря у своєму блозі, а потім опублікувати його на своєму сервері.

var entityMap = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': '&quot;',
    "'": '&#39;',
    "/": '&#x2F;'
  };

  function escapeHtml(string) {
    return String(string).replace(/[&<>"'\/]/g, function (s) {
      return entityMap[s];
    });
  }

Користувач міг:

  • Відредагуйте параметри запиту POST та замініть коментар кодом JavaScript.
  • Перезапишіть функцію escapeHtml за допомогою консолі браузера.

Якщо користувач вставить цей фрагмент у консоль, він обмине перевірку XSS:

function escapeHtml(string){
   return string
}

Я не погоджуюсь. Щоб обійти цей захист XSS, вам доведеться використовувати атаку XSS (введення сценарію, який вимикає втечу), що ви фактично блокуєте. У певних випадках насправді доцільніше втекти від клієнта, наприклад, якщо дані надходять із API REST, який повинен повертати стандартний JSON.
ItalyPaleAle

@Qualcuno Якщо ви робите цю перевірку в клієнті і розміщуєте цю інформацію на сервері, якому довіряєте, вона була перевірена, користувач може просто відредагувати запит, і сценарій буде збережено в базі даних.
Kauê Gimenes

@Qualcuno Я включив кілька прикладів, щоб зробити свою точку більш зрозумілою.
Kauê Gimenes

1
Питання стосувалося виходу рядків, отриманих від сервера для відображення їх у браузері. Що ви говорите про те, щоб уникнути рядків перед тим, як подавати їх на сервер, це вже інша річ (хоча ви маєте рацію, там, і це повертається до старого правила, ніколи сліпо не приймайте жодного внеску від клієнта )
ItalyPaleAle

@Qualcuno Це популярне питання в Stackoverflow, і я вважаю, що це важливий момент, який слід висвітлити. Ось чому я відповів.
Kauê Gimenes

-2

Всі рішення марні , якщо ви не запобігти повторному втечу, наприклад , більшість рішень будуть продовжувати бігти &в &amp;.

escapeHtml = function (s) {
    return s ? s.replace(
        /[&<>'"]/g,
        function (c, offset, str) {
            if (c === "&") {
                var substr = str.substring(offset, offset + 6);
                if (/&(amp|lt|gt|apos|quot);/.test(substr)) {
                    // already escaped, do not re-escape
                    return c;
                }
            }
            return "&" + {
                "&": "amp",
                "<": "lt",
                ">": "gt",
                "'": "apos",
                '"': "quot"
            }[c] + ";";
        }
    ) : "";
};

4
Це називається подвійним проскакуванням і його слід виправити, переконавшись, що ваші вхідні дані вже не вичерпані. Що робити, якщо ти хотів буквально показати & lt; користувачеві? Чи, можливо, текст буде повторно використаний в іншому місці і залежатиме від того, що відбулося уникнення?
thelem
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.