Usuwanie ciągów HTML za pomocą jQuery

Czy ktoś zna prosty sposób na ucieczkę HTML z łańcuchów w jQuery? Muszę być w stanie przekazać dowolny ciąg znaków i mieć go odpowiednio zabezpieczony do wyświetlenia na stronie HTML (zapobieganie atakom JavaScript/HTML injection). Jestem pewien, że można rozszerzyć jQuery, aby to zrobić, ale nie wiem wystarczająco dużo o frameworku w tej chwili, aby to osiągnąć.

Author: Matt Fenwick, 2008-08-24

24 answers

Ponieważ używasz jQuery , możesz po prostu ustawić element text własność:

// 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;
 399
Author: travis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-07 10:09:33

Istnieje również rozwiązanie z wąsów.js

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

function escapeHtml (string) {
  return String(string).replace(/[&<>"'`=\/]/g, function (s) {
    return entityMap[s];
  });
}
 538
Author: Tom Gruner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-13 19:14:50
$('<div/>').text('This is fun & stuff').html(); // "This is fun &amp; stuff"

Źródło: http://debuggable.com/posts/encode-html-entities-with-jquery:480f4dd6-13cc-4ce9-8071-4710cbdd56cb

 176
Author: Henrik N,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-25 22:36:06

Jeśli uciekasz dla HTML, są tylko trzy, które mogą być naprawdę potrzebne:

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

W zależności od przypadku użycia, może być również konieczne wykonanie takich czynności jak " do &quot;. Gdyby lista była wystarczająco duża, użyłbym tablicy:

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() ucieknie tylko dla adresów URL, nie dla HTML.

 58
Author: tghw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-08 14:18:19

Napisałem małą funkcję, która to robi. Ucieka tylko", &, < i > (ale zazwyczaj i tak to wszystko, czego potrzebujesz). Jest nieco bardziej elegancki niż wcześniej proponowane rozwiązania, ponieważ wykorzystuje tylko jeden .replace() do nawrócenia. (EDIT 2: zmniejszono złożoność kodu, dzięki czemu funkcja jest jeszcze mniejsza i schludniejsza, jeśli jesteś ciekawy oryginalnego kodu zobacz koniec tej odpowiedzi.)

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

To jest zwykły Javascript, bez jQuery używany.

Ucieczka / i' też

Edit in response to mklement's comment.

Powyższą funkcję można łatwo rozszerzyć o dowolny znak. Aby określić więcej znaków do ucieczki, po prostu wstaw je zarówno w klasie character w wyrażeniu regularnym (tj. wewnątrz /[...]/g), jak i jako wpis w obiekcie chr. (EDIT 2: skrócono również tę funkcję, w ten sam sposób.)

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

Zwróć uwagę na powyższe użycie &#39; dla apostrophe (encja symboliczna &apos; mogła być używana zamiast – jest zdefiniowana w XML, ale pierwotnie nie była zawarta w specyfikacji HTML i dlatego może nie być obsługiwana przez wszystkie przeglądarki. Zobacz: artykuł Wikipedii na temat kodowania znaków HTML ). Przypominam sobie też, że gdzieś czytałem, że używanie encji dziesiętnych jest bardziej wspierane niż używanie szesnastkowego, ale nie mogę teraz znaleźć źródła do tego. (I nie może być wiele przeglądarek, które nie obsługują byty szesnastkowe.)

Uwaga: dodawanie / i ' do listy znaków zawierających znaki ucieczki nie jest zbyt użyteczne, ponieważ nie mają one specjalnego znaczenia w HTML i nie wymagają .

Original escapeHtml Function

EDIT 2: oryginalna funkcja używała zmiennej (chr) do przechowywania obiektu potrzebnego do wywołania zwrotnego .replace(). Zmienna ta wymagała również dodatkowej funkcji anonimowej do jej zakresu, dzięki czemu funkcja (niepotrzebnie) trochę większy i bardziej złożony.

var escapeHtml = (function () {
    'use strict';
    var chr = { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' };
    return function (text) {
        return text.replace(/[\"&<>]/g, function (a) { return chr[a]; });
    };
}());
Nie testowałem, która z dwóch wersji jest szybsza. Jeśli tak, możesz dodać informacje i linki na ten temat tutaj.
 35
Author: zrajm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-19 15:03:50

Łatwy w użyciu podkreślnik:

_.escape(string) 

Underscore jest biblioteką narzędzi, która zapewnia wiele funkcji, których nie zapewnia natywny js. Istnieje również lodash , który jest tym samym API co podkreślnik, ale został przepisany, aby był bardziej wydajny.

 32
Author: chovy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-02 06:05:04

Zdaję sobie sprawę, jak późno jestem na tej imprezie, ale mam bardzo proste rozwiązanie, które nie wymaga jQuery.

escaped = new Option(unescaped).innerHTML;

Edit: to nie umyka cudzysłowom. Jedynym przypadkiem, w którym cudzysłowy muszą być unikalne, jest to, że zawartość ma być wklejona do atrybutu w ciągu HTML. Trudno mi sobie wyobrazić przypadek, w którym zrobienie tego byłoby dobrym projektem.

Edit 2: jeśli wydajność jest kluczowa, najwyższe rozwiązanie wydajności (o około 50%) jest nadal szeregiem regex zastępuje. Nowoczesne przeglądarki wykryją, że wyrażenia regularne nie zawierają żadnych operatorów, tylko ciąg znaków, i zwiną wszystkie z nich w jedną operację.

 30
Author: Adam Leggett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-08 20:28:27

Oto czysta, przejrzysta funkcja JavaScript. Spowoduje to ucieczkę tekstu, takiego jak "kilka

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;');
}
 26
Author: intrepidis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-20 17:56:57

Spróbuj Podkreślać.string lib, działa z jQuery.

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

Wyjście:

'&lt;div&gt;Blah blah blah&lt;/div&gt;'
 24
Author: Nikita Koksharov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-20 07:36:13

Po ostatnich testach mogę polecić najszybsze i całkowicie cross browser kompatybilne natywne rozwiązanie javaScript (DOM):

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

Jeśli powtórzysz to wiele razy, możesz to zrobić za pomocą raz przygotowanych zmiennych:

//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
}

Spójrz na moje wyniki końcowe porównanie (pytanie stosu ).

 23
Author: Saram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-07 10:54:05

Wzmocniłem wąsy.przykład js dodanie metody escapeHTML() do obiektu string.

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

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

W ten sposób jest dość łatwy w użyciu "Some <text>, more Text&Text".escapeHTML()

 15
Author: Jeena,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-22 10:20:19

escape() i unescape() są przeznaczone do kodowania / dekodowania łańcuchów adresów URL, a nie HTML.

Właściwie, używam poniższego fragmentu, aby zrobić trik, który nie wymaga żadnego frameworka:

var escapedHtml = html.replace(/&/g, '&amp;')
                      .replace(/>/g, '&gt;')
                      .replace(/</g, '&lt;')
                      .replace(/"/g, '&quot;')
                      .replace(/'/g, '&apos;');
 15
Author: NicolasBernier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-08 14:19:01

Jeśli masz podkreślenie.js, użyj _.escape (bardziej wydajna niż metoda jQuery zamieszczona powyżej):

_.escape('Curly, Larry & Moe'); // returns: Curly, Larry &amp; Moe
 10
Author: ronnbot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-08 14:16:18

Jeśli idziesz drogą regex, jest błąd w powyższym przykładzie 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]]);
}
 5
Author: Wayne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-21 21:18:27

To dobry przykład...

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
Author: amrp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-31 01:31:02

Możesz to łatwo zrobić z vanilla js.

Po prostu dodaj tekst do dokumentu. Zostanie on usunięty przez przeglądarkę.

var escaped = document.createTextNode("<HTML TO/ESCAPE/>")
document.getElementById("[PARENT_NODE]").appendChild(escaped)
 3
Author: raam86,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-29 16:34:02
(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));
    };
})();

Brak zmiennych globalnych, trochę optymalizacji pamięci. Sposób użycia:

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

Wynik to:

"some&lt;tag&gt;and&amp;symbol&copy;"
 2
Author: Gheljenor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-13 11:21:59
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);
}
 1
Author: Katharapu Ramana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-29 08:01:35

2 proste metody, które nie wymagają JQUERY...

Możesz zakodować wszystkie znaki w swoim łańcuchu następująco:

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

Lub po prostu kieruj główne postacie , aby martwiły się &, podziały linii, <, >, " i ' Jak:

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>
 1
Author: Dave Brown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-08 14:14:43

Prosty przykład ucieczki 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;"
 1
Author: Andrew Luca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-29 08:23:38
function htmlDecode(t){
   if (t) return $('<div />').html(t).text();
}

Działa jak urok

 0
Author: d-_-b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-03 02:48:33

Ta odpowiedź dostarcza metody jQuery i normal js, ale jest to najkrótsze bez użycia DOM:

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

Escaped string: It%27s%20%3E%2020%25%20less%20complicated%20this%20way.

Jeśli escaped spaces przeszkadza ci, spróbuj:

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

Escaped string: It%27s %3E 20%25 less complicated this way.

Niestety, Funkcja escape() była przestarzała w wersji JavaScript 1.5. encodeURI() lub encodeURIComponent() są alternatywami, ale ignorują ', więc ostatnia linijka kodu zmieni się w to:

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

Wszystkie główne przeglądarki wciąż wesprzyj krótki kod, a biorąc pod uwagę liczbę starych stron internetowych, wątpię, że wkrótce się zmieni.

 0
Author: Cees Timmerman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:46

Jeśli zapisujesz te informacje w bazie danych , błędne jest ukrywanie kodu HTML za pomocą skryptu Po stronie klienta , powinno to być zrobione na serwerze . W przeciwnym razie łatwo obejść ochronę XSS.

Aby wyjaśnić mój punkt widzenia, tutaj jest exemple za pomocą jednej z odpowiedzi:

Powiedzmy, że używasz funkcji escapeHtml, aby uciec Html z komentarza na swoim blogu, a następnie opublikować go na serwerze.

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

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

Użytkownik Może:

  • Edytuj parametry żądania POST i zastąp komentarz kodem javascript.
  • Zastąp funkcję escapeHtml za pomocą konsoli przeglądarki.

Jeśli użytkownik wklei ten fragment do konsoli, ominie walidację XSS:

function escapeHtml(string){
   return string
}
 -2
Author: Kauê Gimenes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-13 18:20:05

Wszystkie rozwiązania są bezużyteczne, jeśli nie zapobiegniesz ponownej ucieczce, np. większość rozwiązań nadal uciekałaby & do &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] + ";";
        }
    ) : "";
};
 -2
Author: C Nimmanant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-08 14:15:24