Javascript HTML Unescape?


176

XML-RPC arka ucuyla iletişim kuran bazı Javascript kodu var. XML-RPC, formun dizelerini döndürür:

<img src='myimage.jpg'>

Ancak, dizeleri HTML'ye eklemek için Javascript kullandığımda, kelimenin tam anlamıyla oluştururlar. Bir görüntü görmüyorum, kelimenin tam anlamıyla dizeyi görüyorum:

<img src='myimage.jpg'>

Benim tahminim HTML XML-RPC kanalı üzerinden kaçıyor olduğunu.

Javascript'te dizenin görünümünü nasıl kaldırabilirim? Bu sayfadaki teknikleri başarısız bir şekilde denedim: http://paulschreiber.com/blog/2008/09/20/javascript-how-to-unescape-html-entities/

Sorunu teşhis etmenin diğer yolları nelerdir?



Yanıtlar:


176

DÜZENLEME: DOMParser API'sini Wladimir'in önerdiği gibi kullanmalısınız, yayınlanan işlev bir güvenlik açığı oluşturduğundan önceki cevabımı düzenledim.

Aşağıdaki snippet, küçük bir değişiklikle eski yanıt kodudur: textareabunun yerine divXSS güvenlik açığını azaltır, ancak IE9 ve Firefox'ta hala sorunludur.

function htmlDecode(input){
  var e = document.createElement('textarea');
  e.innerHTML = input;
  // handle case of empty input
  return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
}

htmlDecode("&lt;img src='myimage.jpg'&gt;"); 
// returns "<img src='myimage.jpg'>"

Temelde programlı bir DOM öğesi oluşturmak, kodlanmış HTML kendi innerHTML atamak ve innerHTML ekleme oluşturulan metin düğümü nodeValue almak. Yalnızca bir öğe oluşturduğundan, ancak hiçbir zaman eklemediğinden, site HTML'si değiştirilmez.

Çapraz tarayıcı (eski tarayıcılar dahil) çalışacak ve tüm HTML Karakter Varlıklarını kabul edecektir .

EDIT: jsFiddle (IE görünümünde) burada kanıtlandığı gibi, bu kodun eski sürümü IE boş girdiler ile çalışmadı . Yukarıdaki sürüm tüm girişlerle çalışır.

GÜNCELLEME: Bu, büyük dize ile çalışmaz ve aynı zamanda bir güvenlik açığı getirir , yorumlara bakın.


Anladım, 'olarak değiştirdin, bu yüzden yorumumu silmeme izin ver, thx, harika çalışıyor, +1
YOU

1
@ S.Mark: &apos;HTML 4 Varlıklarına ait değil, bu yüzden! w3.org/TR/html4/sgml/entities.html fishbowl.pastiche.org/2003/07/01/the_curse_of_apos
CMS

2
Ayrıca bu yaklaşımın zayıf güvenliği hakkında @ kender'in notuna bakınız.
Joseph Turian

2
@Kender'e yaptığı kötü testler hakkındaki notuma bakın;)
Roatin Marth

24
Bu işlev bir güvenlik tehlikesidir, öğe DOM'ye eklenmemiş olsa bile JavaScript kodu çalışır. Yani bu sadece girdi dizgisine güveniliyorsa kullanılacak bir şeydir. Sorunu açıklayan ve güvenli bir çözüm sağlayan kendi cevabımı ekledim . Bir yan etki olarak, birden fazla metin düğümü varsa sonuç kesilmez.
Wladimir Palant

376

Burada verilen cevapların çoğunun büyük bir dezavantajı vardır: dönüştürmeye çalıştığınız dizeye güvenilmiyorsa, bir Siteler Arası Komut Dosyası (XSS) güvenlik açığıyla karşılaşırsınız . Kabul edilen cevaptaki işlev için aşağıdakileri göz önünde bulundurun:

htmlDecode("<img src='dummy' onerror='alert(/xss/)'>");

Buradaki dize, çıkışsız bir HTML etiketi içerir, bu nedenle htmlDecodeişlev, herhangi bir şeyin kodunu çözmek yerine , dizede belirtilen JavaScript kodunu çalıştırır.

Bu, tüm modern tarayıcılarda desteklenen DOMParser kullanılarak önlenebilir :

function htmlDecode(input) {
  var doc = new DOMParser().parseFromString(input, "text/html");
  return doc.documentElement.textContent;
}

console.log(  htmlDecode("&lt;img src='myimage.jpg'&gt;")  )    
// "<img src='myimage.jpg'>"

console.log(  htmlDecode("<img src='dummy' onerror='alert(/xss/)'>")  )  
// ""

Bu işlevin herhangi bir JavaScript kodunu yan etki olarak çalıştırmadığı garanti edilir. Tüm HTML etiketleri yok sayılır, yalnızca metin içeriği döndürülür.

Uyumluluk notu : HTML'yi ayrıştırmak DOMParseriçin en az Chrome 30, Firefox 12, Opera 17, Internet Explorer 10, Safari 7.1 veya Microsoft Edge gerekir. Bu nedenle, desteksiz tüm tarayıcılar EOL'lerini çok geçmiştir ve 2017'den itibaren vahşi doğada hala görülebilen tekler daha eski Internet Explorer ve Safari sürümleridir (genellikle bunlar rahatsız edecek kadar çok değildir).


19
Bence bu cevap en iyisi çünkü XSS güvenlik açığından bahsetti.
Константин Ван

2
(Referansınıza göre) Firefox 12.0'dan önce DOMParserdesteklenmediğini "text/html"ve hala desteklemeyen bazı tarayıcı sürümlerinin hala mevcut olduğunu unutmayınDOMParser.prototype.parseFromString() . Referansınıza göre DOMParser, hala deneysel bir teknolojidir ve stand-in'ler innerHTML, yaklaşımıma yanıt olarak da belirttiğiniz gibi , bu XSS güvenlik açığına (tarayıcı satıcıları tarafından düzeltilmesi gerekir) sahip olan özelliği kullanır.
PointedEars

4
@PointedEars: 2016'da Firefox 12'yi kimin umurunda? Sorunlu olanlar 9.0'a kadar Internet Explorer ve 7.0'a kadar Safari'dir. Biri onları desteklemeyebilirse (ki umarım yakında herkes olacak) o zaman DOMParser en iyi seçimdir. Değilse - evet, yalnızca işlem varlıkları bir seçenek olacaktır.
Wladimir Palant

4
@PointedEars: <script>yürütülmeyen etiketler bir güvenlik mekanizması değildir, bu kural ayarın innerHTMLbir yan etki olarak eşzamanlı komut dosyaları çalıştırabildiğinde zor zamanlama sorunlarını önler . HTML kodunu sterilize etmek zor bir iştir ve innerHTMLdenememektedir - zaten web sayfası satır içi olay işleyicileri ayarlamayı düşünebileceği için. Bu sadece güvensiz veriler için tasarlanmış bir mekanizma değildir, tam durma.
Wladimir Palant

1
@ ИльяЗеленько: Bu kodu sıkı bir döngüde kullanmayı planlıyor musunuz veya performans neden önemlidir? Cevabınız yine XSS'ye karşı savunmasız, buna gerçekten değdi mi?
Wladimir Palant

37

JQuery kullanıyorsanız:

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

Aksi takdirde, Strictly Software'in mükemmel bir htmlDecode()işlevi olan Kodlayıcı Nesnesini kullanın .


59
Tarafından üretilen kullanıcı tarafından oluşturulan içerik diğerinden daha içerik için bu kullanmaz (tekrarlamak DEĞİL) Do Bu kullanıcının. Değerde bir <script> etiketi varsa, komut dosyasının içeriği yürütülür!
Malvolio

Sitenin hiçbir yerinde bunun için bir lisans bulamıyorum. Lisansın ne olduğunu biliyor musun?
TRiG

Kaynak başlığında bir lisans var, bu GPL.
Chris Fulstow

6
EVET, bu işlev XSS'in yolunu açar: htmlDecode'u deneyin ("<script> alert (12) </script> 123 & gt;"))
Dinis Cruz

$ ('<div />') ne anlama geliyor ?
Echo Yang

13

İşin püf noktası, özel HTML karakterlerinin kodunu çözmek için tarayıcının gücünü kullanmaktır, ancak tarayıcının sonuçları gerçek html gibi yürütmesine izin vermektir ... Bu işlev, kodlanmış HTML karakterlerini (bir karakter) tanımlamak ve değiştirmek için bir normal ifade kullanır zamanında.

function unescapeHtml(html) {
    var el = document.createElement('div');
    return html.replace(/\&[#0-9a-z]+;/gi, function (enc) {
        el.innerHTML = enc;
        return el.innerText
    });
}

Normal ifade biraz daha sıkı bir şekilde eşleştirilebilir, /\&#?[0-9a-z]+;/giçünkü # ise yalnızca 2. karakter olarak görünmelidir.
TheAtomicOption

Bu en iyi cevap. XSS güvenlik açığından kaçınır ve HTML etiketlerini çıkarmaz.
Emmanuel

6

Ekran görüntüsünü kaldırmak istediğiniz HTML çok uzun değilse, 65536 karakterden uzun olmadığı sürece CMS'nin cevabı iyi çalışır. Çünkü daha sonra Chrome'da iç HTML, her biri en fazla 65536 uzunluğunda birçok alt düğüme ayrılır ve bunları birleştirmeniz gerekir. Bu işlev çok uzun dizelerde de çalışır:

function unencodeHtmlContent(escapedHtml) {
  var elem = document.createElement('div');
  elem.innerHTML = escapedHtml;
  var result = '';
  // Chrome splits innerHTML into many child nodes, each one at most 65536.
  // Whereas FF creates just one single huge child node.
  for (var i = 0; i < elem.childNodes.length; ++i) {
    result = result + elem.childNodes[i].nodeValue;
  }
  return result;
}

Daha innerHTMLfazla bilgi için maksimum uzunluk ile ilgili bu yanıta bakın : https://stackoverflow.com/a/27545633/694469


3

Sorunuza doğrudan bir yanıt değil, ancak RPC'nizin bu yapıdaki bu görüntü verileriyle (örneğin URL'ler) bir yapı (XML veya JSON veya başka bir şekilde) döndürmesi daha iyi olmaz mı?

Sonra sadece javascript içinde ayrıştırmak ve <img>kullanarak javascript kendisi inşa edebilirsiniz .

RPC'den aldığınız yapı şöyle görünebilir:

{"img" : ["myimage.jpg", "myimage2.jpg"]}

Dış kaynaktan gelen bir kodu sayfanıza eklemek çok güvenli görünmediğinden, bu şekilde daha iyi olduğunu düşünüyorum. Birisinin XML-RPC betiğinizi ele geçirdiğini ve orada istemeyeceğiniz bir şeyi koyduğunu görüntüleme (hatta bazı javascriptler ...)


Yukarıdaki @CMS yaklaşımında bu güvenlik açığı var mı?
Joseph Turian

Ben sadece htmlDecode fuction geçirilen aşağıdaki bağımsız değişkeni kontrol ettim: htmlDecode ("& lt; img src = 'myimage.jpg' & gt;" script & gt; document.write ('xxxxx'); & lt; / script & gt; ") ve <script> </script> öğesi kötü olabilir, imho. Ve hala eklenecek metin yerine bir yapı döndürmenin daha iyi olduğunu düşünüyorum, örneğin hataları güzel işleyebilirsiniz.
kender

1
Sadece denedim htmlDecode("&lt;img src='myimage.jpg'&gt;&lt;script&gt;alert('xxxxx');&lt;/script&gt;")ve hiçbir şey olmadı. Beklendiği gibi kodu çözülmüş html dizesini aldım.
Roatin Marth

2

Chris cevap güzel ve zarif ama değer tanımsız ise başarısız . Sadece basit iyileştirme sağlamlaştırır:

function htmlDecode(value) {
   return (typeof value === 'undefined') ? '' : $('<div/>').html(value).text();
}

İyileştirirseniz, return (typeof value !== 'string') ? '' : $('<div/>').html(value).text();
şunları yapın

2

Rica ederim ... sadece bir haberci ... tam kredi, aşağıdaki kodumuzaworld.com'a gidiyor.

window.htmlentities = {
        /**
         * Converts a string to its html characters completely.
         *
         * @param {String} str String with unescaped HTML characters
         **/
        encode : function(str) {
            var buf = [];

            for (var i=str.length-1;i>=0;i--) {
                buf.unshift(['&#', str[i].charCodeAt(), ';'].join(''));
            }

            return buf.join('');
        },
        /**
         * Converts an html characterSet into its original character.
         *
         * @param {String} str htmlSet entities
         **/
        decode : function(str) {
            return str.replace(/&#(\d+);/g, function(match, dec) {
                return String.fromCharCode(dec);
            });
        }
    };

Tam Kredi: https://ourcodeworld.com/articles/read/188/encode-and-decode-html-entities-using-pure-javascript


2

Bu şimdiye kadar denediğim en kapsamlı çözüm:

const STANDARD_HTML_ENTITIES = {
    nbsp: String.fromCharCode(160),
    amp: "&",
    quot: '"',
    lt: "<",
    gt: ">"
};

const replaceHtmlEntities = plainTextString => {
    return plainTextString
        .replace(/&#(\d+);/g, (match, dec) => String.fromCharCode(dec))
        .replace(
            /&(nbsp|amp|quot|lt|gt);/g,
            (a, b) => STANDARD_HTML_ENTITIES[b]
        );
};

"En kapsamlı"? Gerçekten kapsamlı bir test paketine karşı çalıştırmayı denediniz mi?
Dan Dascalescu

1

Tamamen olmasa da güzel olması gereken bu işlevi yerine getirecek kadar deli oldum:

function removeEncoding(string) {
    return string.replace(/&Agrave;/g, "À").replace(/&Aacute;/g, "Á").replace(/&Acirc;/g, "Â").replace(/&Atilde;/g, "Ã").replace(/&Auml;/g, "Ä").replace(/&Aring;/g, "Å").replace(/&agrave;/g, "à").replace(/&acirc;/g, "â").replace(/&atilde;/g, "ã").replace(/&auml;/g, "ä").replace(/&aring;/g, "å").replace(/&AElig;/g, "Æ").replace(/&aelig;/g, "æ").replace(/&szlig;/g, "ß").replace(/&Ccedil;/g, "Ç").replace(/&ccedil;/g, "ç").replace(/&Egrave;/g, "È").replace(/&Eacute;/g, "É").replace(/&Ecirc;/g, "Ê").replace(/&Euml;/g, "Ë").replace(/&egrave;/g, "è").replace(/&eacute;/g, "é").replace(/&ecirc;/g, "ê").replace(/&euml;/g, "ë").replace(/&#131;/g, "ƒ").replace(/&Igrave;/g, "Ì").replace(/&Iacute;/g, "Í").replace(/&Icirc;/g, "Î").replace(/&Iuml;/g, "Ï").replace(/&igrave;/g, "ì").replace(/&iacute;/g, "í").replace(/&icirc;/g, "î").replace(/&iuml;/g, "ï").replace(/&Ntilde;/g, "Ñ").replace(/&ntilde;/g, "ñ").replace(/&Ograve;/g, "Ò").replace(/&Oacute;/g, "Ó").replace(/&Ocirc;/g, "Ô").replace(/&Otilde;/g, "Õ").replace(/&Ouml;/g, "Ö").replace(/&ograve;/g, "ò").replace(/&oacute;/g, "ó").replace(/&ocirc;/g, "ô").replace(/&otilde;/g, "õ").replace(/&ouml;/g, "ö").replace(/&Oslash;/g, "Ø").replace(/&oslash;/g, "ø").replace(/&#140;/g, "Œ").replace(/&#156;/g, "œ").replace(/&#138;/g, "Š").replace(/&#154;/g, "š").replace(/&Ugrave;/g, "Ù").replace(/&Uacute;/g, "Ú").replace(/&Ucirc;/g, "Û").replace(/&Uuml;/g, "Ü").replace(/&ugrave;/g, "ù").replace(/&uacute;/g, "ú").replace(/&ucirc;/g, "û").replace(/&uuml;/g, "ü").replace(/&#181;/g, "µ").replace(/&#215;/g, "×").replace(/&Yacute;/g, "Ý").replace(/&#159;/g, "Ÿ").replace(/&yacute;/g, "ý").replace(/&yuml;/g, "ÿ").replace(/&#176;/g, "°").replace(/&#134;/g, "†").replace(/&#135;/g, "‡").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&#177;/g, "±").replace(/&#171;/g, "«").replace(/&#187;/g, "»").replace(/&#191;/g, "¿").replace(/&#161;/g, "¡").replace(/&#183;/g, "·").replace(/&#149;/g, "•").replace(/&#153;/g, "™").replace(/&copy;/g, "©").replace(/&reg;/g, "®").replace(/&#167;/g, "§").replace(/&#182;/g, "¶").replace(/&Alpha;/g, "Α").replace(/&Beta;/g, "Β").replace(/&Gamma;/g, "Γ").replace(/&Delta;/g, "Δ").replace(/&Epsilon;/g, "Ε").replace(/&Zeta;/g, "Ζ").replace(/&Eta;/g, "Η").replace(/&Theta;/g, "Θ").replace(/&Iota;/g, "Ι").replace(/&Kappa;/g, "Κ").replace(/&Lambda;/g, "Λ").replace(/&Mu;/g, "Μ").replace(/&Nu;/g, "Ν").replace(/&Xi;/g, "Ξ").replace(/&Omicron;/g, "Ο").replace(/&Pi;/g, "Π").replace(/&Rho;/g, "Ρ").replace(/&Sigma;/g, "Σ").replace(/&Tau;/g, "Τ").replace(/&Upsilon;/g, "Υ").replace(/&Phi;/g, "Φ").replace(/&Chi;/g, "Χ").replace(/&Psi;/g, "Ψ").replace(/&Omega;/g, "Ω").replace(/&alpha;/g, "α").replace(/&beta;/g, "β").replace(/&gamma;/g, "γ").replace(/&delta;/g, "δ").replace(/&epsilon;/g, "ε").replace(/&zeta;/g, "ζ").replace(/&eta;/g, "η").replace(/&theta;/g, "θ").replace(/&iota;/g, "ι").replace(/&kappa;/g, "κ").replace(/&lambda;/g, "λ").replace(/&mu;/g, "μ").replace(/&nu;/g, "ν").replace(/&xi;/g, "ξ").replace(/&omicron;/g, "ο").replace(/&piρ;/g, "ρ").replace(/&rho;/g, "ς").replace(/&sigmaf;/g, "ς").replace(/&sigma;/g, "σ").replace(/&tau;/g, "τ").replace(/&phi;/g, "φ").replace(/&chi;/g, "χ").replace(/&psi;/g, "ψ").replace(/&omega;/g, "ω").replace(/&bull;/g, "•").replace(/&hellip;/g, "…").replace(/&prime;/g, "′").replace(/&Prime;/g, "″").replace(/&oline;/g, "‾").replace(/&frasl;/g, "⁄").replace(/&weierp;/g, "℘").replace(/&image;/g, "ℑ").replace(/&real;/g, "ℜ").replace(/&trade;/g, "™").replace(/&alefsym;/g, "ℵ").replace(/&larr;/g, "←").replace(/&uarr;/g, "↑").replace(/&rarr;/g, "→").replace(/&darr;/g, "↓").replace(/&barr;/g, "↔").replace(/&crarr;/g, "↵").replace(/&lArr;/g, "⇐").replace(/&uArr;/g, "⇑").replace(/&rArr;/g, "⇒").replace(/&dArr;/g, "⇓").replace(/&hArr;/g, "⇔").replace(/&forall;/g, "∀").replace(/&part;/g, "∂").replace(/&exist;/g, "∃").replace(/&empty;/g, "∅").replace(/&nabla;/g, "∇").replace(/&isin;/g, "∈").replace(/&notin;/g, "∉").replace(/&ni;/g, "∋").replace(/&prod;/g, "∏").replace(/&sum;/g, "∑").replace(/&minus;/g, "−").replace(/&lowast;/g, "∗").replace(/&radic;/g, "√").replace(/&prop;/g, "∝").replace(/&infin;/g, "∞").replace(/&OEig;/g, "Œ").replace(/&oelig;/g, "œ").replace(/&Yuml;/g, "Ÿ").replace(/&spades;/g, "♠").replace(/&clubs;/g, "♣").replace(/&hearts;/g, "♥").replace(/&diams;/g, "♦").replace(/&thetasym;/g, "ϑ").replace(/&upsih;/g, "ϒ").replace(/&piv;/g, "ϖ").replace(/&Scaron;/g, "Š").replace(/&scaron;/g, "š").replace(/&ang;/g, "∠").replace(/&and;/g, "∧").replace(/&or;/g, "∨").replace(/&cap;/g, "∩").replace(/&cup;/g, "∪").replace(/&int;/g, "∫").replace(/&there4;/g, "∴").replace(/&sim;/g, "∼").replace(/&cong;/g, "≅").replace(/&asymp;/g, "≈").replace(/&ne;/g, "≠").replace(/&equiv;/g, "≡").replace(/&le;/g, "≤").replace(/&ge;/g, "≥").replace(/&sub;/g, "⊂").replace(/&sup;/g, "⊃").replace(/&nsub;/g, "⊄").replace(/&sube;/g, "⊆").replace(/&supe;/g, "⊇").replace(/&oplus;/g, "⊕").replace(/&otimes;/g, "⊗").replace(/&perp;/g, "⊥").replace(/&sdot;/g, "⋅").replace(/&lcell;/g, "⌈").replace(/&rcell;/g, "⌉").replace(/&lfloor;/g, "⌊").replace(/&rfloor;/g, "⌋").replace(/&lang;/g, "⟨").replace(/&rang;/g, "⟩").replace(/&loz;/g, "◊").replace(/&#039;/g, "'").replace(/&amp;/g, "&").replace(/&quot;/g, "\"");
}

Şöyle kullanılır:

let decodedText = removeEncoding("Ich hei&szlig;e David");
console.log(decodedText);

Baskılar: Ich Heiße David

PS bu yapmak bir buçuk saat sürdü.


0

JavaScript'teki HTML varlıklarının * görünümünü kaldırmak için küçük kitaplık html-escaper kullanabilirsiniz :npm install html-escaper

import {unescape} from 'html-escaper';

unescape('escaped string');

Veya unescapegelen fonksiyon Lodash veya alt çizgi , bunu kullanıyorsanız.


* Bu işlevler tüm HTML öğelerini kapsayacak, ancak olmadığını) lütfen not sadece en yaygın olanları, yani &, <, >, ', ". Tüm HTML öğelerini okunabilir hale getirmek için kullanabileceğiniz o kütüphane.


-1

Bunu projemde kullanıyorum: diğer cevaplardan esinlenerek, ancak ekstra güvenli bir parametreyle, süslü karakterlerle uğraşırken faydalı olabilir

var decodeEntities=(function(){

    var el=document.createElement('div');
    return function(str, safeEscape){

        if(str && typeof str === 'string'){

            str=str.replace(/\</g, '&lt;');

            el.innerHTML=str;
            if(el.innerText){

                str=el.innerText;
                el.innerText='';
            }
            else if(el.textContent){

                str=el.textContent;
                el.textContent='';
            }

            if(safeEscape)
                str=str.replace(/\</g, '&lt;');
        }
        return str;
    }
})();

Ve şu şekilde kullanılabilir:

var label='safe <b> character &eacute;ntity</b>';
var safehtml='<div title="'+decodeEntities(label)+'">'+decodeEntities(label, true)+'</div>';

-1

Buradaki diğer cevapların hepsinde sorun var.

Document.createElement ('div') yöntemleri (jQuery kullananları da dahil olmak üzere) içine aktarılan herhangi bir javascript'i çalıştırır (güvenlik sorunu) ve DOMParser.parseFromString () yöntemi boşlukları düzeltir. İşte hiçbir sorunu olmayan saf bir javascript çözümü:

function htmlDecode(html) {
    var textarea = document.createElement("textarea");
    html= html.replace(/\r/g, String.fromCharCode(0xe000)); // Replace "\r" with reserved unicode character.
    textarea.innerHTML = html;
    var result = textarea.value;
    return result.replace(new RegExp(String.fromCharCode(0xe000), 'g'), '\r');
}

TextArea özellikle js kodunun yürütülmesini önlemek için kullanılır. Bunları geçer:

htmlDecode('&lt;&amp;&nbsp;&gt;'); // returns "<& >" with non-breaking space.
htmlDecode('  '); // returns "  "
htmlDecode('<img src="dummy" onerror="alert(\'xss\')">'); // Does not execute alert()
htmlDecode('\r\n') // returns "\r\n", doesn't lose the \r like other solutions.

1
Hayır, farklı bir etiket kullanarak yok değil sorunu çözmek. Bu hala bir XSS güvenlik açığıdır, deneyin htmlDecode("</textarea><img src=x onerror=alert(1)>"). Sergio Belevskij'nin cevabına bu konuyu işaret ettikten sonra bunu gönderdiniz.
Wladimir Palant

Açıkladığınız sorunu yeniden oluşturamıyorum. Bu JsFiddle kodunuz var ve çalışırken hiçbir uyarı görüntüler. jsfiddle.net/edsjt15g/1 Bir göz atabilir misiniz? Hangi tarayıcıyı kullanıyorsunuz?
EricP

2
Firefox kullanıyorum. Chrome gerçekten de bu senaryoyu farklı şekilde ele alıyor, bu nedenle kod yürütülmüyor - ancak güvenmeniz gereken bir şey değil.
Wladimir Palant

-1
var encodedStr = 'hello &amp; world';

var parser = new DOMParser;
var dom = parser.parseFromString(
    '<!doctype html><body>' + encodedStr,
    'text/html');
var decodedString = dom.body.textContent;

console.log(decodedString);

@Wladimir Palant (AdBlock Plus'ın yazarı) zaten DOMParser'a 4 yıl önce cevap verdi . Sizinkini göndermeden önce önceki cevapları okudunuz mu?
Dan Dascalescu

-7

En tepedeki cevapların% 80'i kadar verimli bir varyant var.

Karşılaştırmaya bakın: https://jsperf.com/decode-html12345678/1

performans testi

console.log(decodeEntities('test: &gt'));

function decodeEntities(str) {
  // this prevents any overhead from creating the object each time
  const el = decodeEntities.element || document.createElement('textarea')

  // strip script/html tags
  el.innerHTML = str
    .replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '')
    .replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '');

  return el.value;
}

Etiketleri bırakmanız gerekiyorsa, iki .replace(...)aramayı kaldırın (komut dosyalarına ihtiyacınız yoksa ilk aramayı bırakabilirsiniz).


6
Tebrikler, güvenlik açığı sahte sanitizaion mantığı ile gizlemeyi başardınız, hepsi pratikte önemli olmayan bir performans kazancı için. decodeEntities("</textarea '><img src=x onerror=alert(1) \">")Firefox'ta aramayı deneyin . Lütfen HTML kodunu normal ifadelerle sterilize etmeye çalışmayın.
Wladimir Palant
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.