HTML varlıklarını jQuery kullanarak nasıl çözebilirim?


Yanıtlar:


437

Güvenlik notu: Bu cevabı kullanmak (aşağıdaki orijinal formunda korunur) uygulamanıza bir XSS güvenlik açığı getirebilir. Bu cevabı kullanmamalısınız. Bu cevaptaki güvenlik açıklarının açıklaması için lucascaro'nun cevabını okuyun ve bunun yerine ya bu cevabın ya da Mark Amery'nin cevabının yaklaşımını kullanın.

Aslında, dene

var decoded = $("<div/>").html(encodedStr).text();

175
Do not güvenilmeyen girişli bunu. Düğüm DOM'a bağlı olmasa bile birçok tarayıcı resim ve ateşle ilgili olayları yükler. Koşmayı deneyin $("<div/>").html('<img src="http://www.google.com/images/logos/ps_logo2.png" onload=alert(1337)>'). Firefox veya Safari'de uyarıyı tetikler.
Mike Samuel

@Mike, bunun yerine ne öneriyorsun? neyi değiştirdiğinizi bilmiyorsanız .replace () yanıtınız iyi değil ...
Ekkis

7
@ekkis, varlıkları deşifre etmeye çalışmadan önce etiketleri çıkarmanız gerekir. str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/g, "")Veya benzeri.
Mike Samuel

2
Çoğu HTML etiketini (Mike'ın nezaketiyle) girdiden ayıran daha iyi bir uygulama (bence) benzer bir soruya cevabımda . Ayrıca jQuery yükü yoktur, bu nedenle diğer ortamlar için oldukça uygundur.
Robert K

6
@MichaelStum, buradaki düzenlemeniz hem Mike Samuel'in yorumunu hem de bir sonraki en yüksek oyu alan cevabı geçersiz kıldı ve bunu tüm jQuery sürümleri için XSS güvenlik açığını gerçekten düzeltmeden yaptı (aşağıdaki cevapta açıklandığı gibi). Bu yanıta bir güvenlik uyarısı eklemek mantıklı olacaktır (ve ben de yapacağım); güvenlik açığı tam olarak çözülemediğinde, bu sayfada başka bir tartışmayı saçma hale getirmek kesinlikle değil!
Mark Amery

211

Herhangi bir jQuery olmadan:

function decodeEntities(encodedString) {
  var textArea = document.createElement('textarea');
  textArea.innerHTML = encodedString;
  return textArea.value;
}

console.log(decodeEntities('1 &amp; 2')); // '1 & 2'

Bu, kabul edilen cevaba benzer şekilde çalışır , ancak güvenilir olmayan kullanıcı girişiyle kullanmak güvenlidir.


Benzer yaklaşımlardaki güvenlik sorunları

Mike Samuel'in belirttiği gibi , bunu güvenilmeyen bir kullanıcı girişi <div>yerine <textarea>bununla <div>yapmak, DOM'a hiç eklenmemiş olsa bile bir XSS güvenlik açığıdır :

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)">')

Ancak, bu saldırıya karşı mümkün değildir <textarea>çünkü a içeriğine izin verilen HTML öğeleri yoktur <textarea>. Sonuç olarak, 'kodlanmış' dizede bulunan tüm HTML etiketleri tarayıcı tarafından otomatik olarak varlık tarafından kodlanır.

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)">'))

Uyarı : Bunu yapmak yerine jQuery .html()ve .val()yöntemlerini kullanarak yapmak .innerHTMLve .valueaynı zamanda jQuery'nin bazı sürümleri için biletextarea güvenli değildir * . Bunun nedeni, jQuery'nin eski sürümlerinin, geçirilen dizede bulunan komut dosyalarını kasıtlı ve açık bir şekilde değerlendirmesidir.html() . Bu nedenle bu kod jQuery 1.8 bir uyarı gösterir:

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

* Bu zafiyeti yakaladığı için Eru Penkman'a teşekkürler .


6
Değerini çıkardıktan sonra textarea imha etmek iyi bir fikir olabilir:decodedString = textArea.value; textArea.remove(); return decodedString;
Werner

2
Veya sadece javascript sürümü gerçekten remove () destekliyorsa:if ('remove' in Element.prototype) textArea.remove();
Werner

6
@Werner İşlevden çıkar çıkmaz, ona referans tutan başka değişken olmayacak, böylece çöp toplayıcı tarafından otomatik olarak kaldırılacaktır .
user2428118

Ben bir düğme tıklama arkasındaki kod arkasından .NET ile birlikte bu kullanıyorum ve bazı nedenlerden dolayı kabul edilen yanıt bir geri gönderme neden oldu. Bu cevap vermedi, bu yüzden bu benim için en iyi cevap. Teşekkürler!
Snailer

@Snailer $("<div />").html(string).text() sağlanan dize herhangi bir javascript yürütecek , hangi sorun neden olduğunu şüpheli. Kabul edilen cevap bu cevapla güncellenmelidir.
jbowman

80

Mike Samuel'in dediği gibi, html varlıklarını güvensiz olduğu için kod çözmek için jQuery.html (). Text () kullanmayın.

Bunun yerine, gibi bir şablon oluşturucusunu kullanmak Mustache.js veya decodeEntities VyvIT yorumuna @ dan.

Underscore.js yardımcı kemer kitaplığı ile birlikte gelir escapeve unescapeyöntemler, ancak kullanıcı girişi için güvenli değildir:

_.escape (dize)

_.unescape (dize)


2
Bu aslında daha fazla oyu hak ediyor! Kesinlikle benim tercih ettiğim çözüm. unescapeŞimdiye kadar belgelere dahil ettiler , btw.
ölümcül gitar

5
_.unescape("&#39;")sadece "& # 39" ile sonuçlanır tek tırnak yerine. Eksik olduğum bir şey var mı veya HTML varlık kodlarına gösterildiği gibi alt çizgi kaçmıyor: w3schools.com/tags/ref_entities.asp
Jason Axelson

6
Github'daki hata "Düzeltilmeyecek" olarak kapatıldı; Bu, bu çözümün çalışmadığı ve çalışmadığı anlamına gelir.
Igor Chubin

3
Alt çizgi " escapeve unescapeyöntemleri ... kullanıcı girişi için güvenli değil " diyorsunuz . Bununla ne demek istiyorsun? Bana saçma geliyor, ama belki bir şeyleri kaçırıyorum - açıklığa kavuşturabilir misin?
Mark Amery

2
@VyvIT Denendi _.unescape("&lt;img src=fake onerror=alert('boo!')&gt;")(Chrome / FF / IE'de). Ama olmadı , herhangi bir uyarı görünür. Konsolda denedim ve JS dosyama da koydu. Aynı sonuç.
Vivek Athalye

28

Metin ve HTML yöntemlerini karıştırdığınızı düşünüyorum. Bu örneğe bakın, bir öğenin iç HTML'sini metin olarak kullanırsanız, kodu çözülmüş HTML etiketleri alırsınız (ikinci düğme). Ancak bunları HTML olarak kullanırsanız, HTML biçimli görünümü alırsınız (ilk düğme).

<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());" />
&nbsp;&nbsp;
<input value="Write as Text" type="button" onclick="javascript:$('#resultDiv').text($('#myDiv').html());" />
<br /><br />
<div id="resultDiv">
    Results here !
</div>

İlk düğme yazıyor: İşte bir HTML içeriği.

İkinci düğme şöyle yazar: İşte bir <B> HTML </B> içeriği.

Bu arada, jQuery eklentisinde bulduğum bir eklentiyi görebilirsiniz - HTML kodunu ve HTML dizelerini kodlayan ve kodunu çözen kodlama .


26

Soru 'jQuery ile' sınırlıdır, ancak bazılarının burada en iyi cevapta verilen jQuery kodunun altında aşağıdakileri yaptığını bilmesine yardımcı olabilir ... bu jQuery ile veya jQuery olmadan çalışır:

function decodeEntities(input) {
  var y = document.createElement('textarea');
  y.innerHTML = input;
  return y.value;
}

20

Https://github.com/mathiasbynens/he adresinde bulunan he kütüphanesini kullanabilirsiniz.

Misal:

console.log(he.decode("J&#246;rg &amp J&#xFC;rgen rocked to &amp; fro "));
// Logs "Jörg & Jürgen rocked to & fro"

Ben kütüphanenin yazar meydan lehine clientside kodunda bu kütüphaneyi kullanmak için herhangi bir neden yoktu olmadığının sorulması üzerine <textarea>sağlanan hack diğer yanıtlar burada ve başka yerlerde. Birkaç olası gerekçe sağladı:

  • Node.js sunucu tarafı kullanıyorsanız, HTML kodlama / kod çözme için bir kitaplık kullanmak, hem istemci tarafında hem de sunucu tarafında çalışan tek bir çözüm sunar.

  • Bazı tarayıcıların varlık kod çözme algoritmalarında hatalar vardır veya bazı adlandırılmış karakter referansları için destek eksiktir . Örneğin, Internet Explorer kırılmayan boşlukların hem kodunu çözer hem de oluşturur ( &nbsp;) ancak bir DOM öğesinin innerTextözelliği aracılığıyla <textarea>kesmeyi kırmak yerine sıradan boşluklar olarak bildirir (yalnızca küçük bir şekilde de olsa). Ayrıca, IE 8 ve 9 basit desteklemez yazarı HTML 5. eklenen yeni adlandırılmış karakter referansların herhangi kendisinden ayrıca adında karakter referans destek testini barındıran http://mathias.html5.org/tests/html / adlandırılmış karakter referansları . IE 8'de binden fazla hata bildiriyor.

    Varlık kod çözme ile ilgili tarayıcı hatalarından yalıtılmak ve / veya adlandırılmış karakter referanslarının tamamını işleyebilmek istiyorsanız, <textarea>saldırıdan kurtulamazsınız ; onun gibi bir kütüphaneye ihtiyacın olacak .

  • Sadece lanet olsun, işleri bu şekilde yapmak daha az hileli gibi geliyor.


4
+1 jQuery her şeyin çözümü değildir. İş için doğru aracı kullanın.
Mathias Bynens

Bunlar HTML varlıklarının kodunu çözmenin en iyi yoludur. Diğer tüm cevaplar (bu ve benzer sorularda) innerHTML kullanır (yeni HTML öğesi oluştur, HTML kodunu işler ve sonra bu öğenin innerHTML'sini alır, ÇOK dikkatli değilseniz, daha fazla bilgi görürseniz , bu XSS saldırılarına karşı savunmasız olabilir veya bunlar her ikisi de eksik olan Underscore.js unescape veya Lodash unescape yöntemlerini kullanmanızı öneririz (yalnızca birkaç HTML varlığı için çalışır). Kütüphanesi en eksiksiz ve güvenli seçenektir!
ands

18

kodlamak:

$("<textarea/>").html('<a>').html();      // return '&lt;a&gt'

kod çözme:

$("<textarea/>").html('&lt;a&gt').val()   // return '<a>'

3
zaten çalışan bir cevap var ve neredeyse bununla aynı. Yinelenen cevaplara ihtiyacımız yok
markasoftware

4
Bu geçerli bir cevap. tom'un cevabı, bu cevabı XSS'ye karşı savunmasız hale getiren bir DIV elemanı kullanır.
Francisco Hodge

2
Açıklık için en iyi cevap budur.
Dan Randolph

4

kullanım

myString = myString.replace( /\&amp;/g, '&' );

Görünüşe göre JavaScript'in varlıkları işlemek için yerel bir kütüphanesi olmadığı veya JavaScript'i genişleten çeşitli çerçeveler için arama sonuçlarının üst kısmına yakın herhangi bir şey bulamadığım için bunu sunucu tarafında yapmak en kolay yoldur.

"JavaScript HTML varlıkları" için arama yapın ve yalnızca bu amaçla birkaç kitaplık bulabilirsiniz, ancak büyük olasılıkla bunların tümü yukarıdaki mantık etrafında oluşturulacaktır.


0

Ben sadece bir HTML düğmesi için bir değer olarak bir HTML varlık karakter (⇓) olması gerekiyordu. HTML kodu tarayıcıda baştan iyi görünüyor:

<input type="button" value="Embed & Share  &dArr;" id="share_button" />

Şimdi karakterleri de göstermesi gereken bir geçiş ekliyordum. Bu benim çözümüm

$("#share_button").toggle(
    function(){
        $("#share").slideDown();
        $(this).attr("value", "Embed & Share " + $("<div>").html("&uArr;").text());
    }

Düğmede ⇓ tekrar görüntülenir. Umarım bu birine yardımcı olabilir.


Daha basit olan, bir unicode kaçış dizisi (yani "Embed & Share \u21d1") kullanmak ya da sadece "Embed & Share ⇑"komut dosyanızı UTF-8'de (veya UTF-16'da veya ⇑ karakterini destekleyen başka bir kodlamada) sunabiliyorsanız daha iyi olabilir. Bir HTML öğesini yalnızca rastgele bir unicode karakteri JavaScript dizesine dönüştürmek için bir DOM öğesi kullanmak, Rube Goldberg'i gururlandıracak, ancak iyi bir uygulama olmayan kurnaz ve yaratıcı bir yaklaşımdır; unicode kaçışları bu kullanım durumunu ele almak için özel olarak dildedir.
Mark Amery

0

Html varlıkları için özel işlev yapmanız gerekir:

function htmlEntities(str) {
return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g,'&gt;').replace(/"/g, '&quot;');
}

Hiçbir fikrim yok, bu bana çok yardımcı oldu +1 l-)
Szymon Toda

muhtemelen sadece bazı varlıkları ele aldığı için oylandı.
Jasen

Orijinal soru, varlıkların kodunun nasıl çözüleceğiydi - bu , istenen şeyin tam tersini yapar ; o kodlar karakterlerin son derece sınırlı bir set haline varlıklar. Aşağı oy araç ipucunun dediği gibi "Bu cevap yararlı değil". 4 yıl sonra hala net-pozitif puan alması beni şaşırttı.
Stephen P

0

Dize'nin altında olduğunu varsayalım.

Deluxe kabinlerimiz sıcak, rahat & amp; rahat

var str = $("p").text(); // get the text from <p> tag
$('p').html(str).text();  // Now,decode html entities in your variable i.e 

str ve a ata

etiket.

bu kadar.


0

ExtJS kullanıcıları için, kodlanmış bir dizeye zaten sahipseniz, örneğin bir kütüphane işlevinin döndürülen değeri innerHTML içeriği ise, bu ExtJS işlevini göz önünde bulundurun:

Ext.util.Format.htmlDecode(innerHtmlContent)

Bu yalnızca 5 HTML varlığı için çalışır. Bunu dokümantasyonda ve kaynak kodunda görebilirsiniz .
ands

0

Bir String sınıfını genişletme:

String::decode = ->
  $('<textarea />').html(this).text()

ve yöntem olarak kullanın:

"&lt;img src='myimage.jpg'&gt;".decode()

0

Bunu dene :

var htmlEntities = "&lt;script&gt;alert('hello');&lt;/script&gt;";
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 kitaplığındaki bir ve verilen Dize hakkında bazı ayrıntılar içeren bir dizi döndürür.

bazı durumlarda Dize büyük olduğundan işlev içeriği birçok dizine ayıracaktır.

ve tüm indeks verilerini almak için herhangi bir endekse gitmeli ve daha sonra "wholeText" adlı indekse erişmelisiniz.

Tüm durumlarda (küçük Dize veya büyük dize) çalışacağından dizin 0'ı seçtim.


Bu kod snippet'i çözüm olsa da, bir açıklama da dahil olmak üzere mesajınızın kalitesini artırmaya yardımcı olur. Gelecekte okuyucular için soruyu cevapladığınızı ve bu kişilerin kod önerinizin nedenlerini bilmeyebileceğini unutmayın.
Johan

Açıklama eklendi ... Teşekkürler :)
Fawaz Al Romy

-1

Hala bir sorun var: Giriş değerine atandığında çıkış karakterli dize okunamıyor

var string = _.escape("<img src=fake onerror=alert('boo!')>");
$('input').val(string);

Örnek: https://jsfiddle.net/kjpdwmqa/3/


Bu sorunun cevabı değil. OP, HTML varlığının kodunu çözmeyi (unescape) istiyor, ancak bu cevapta escapeUnderscore.js yöntemini kullanıyorsunuz . Ayrıca kod örneğinizin OP sorununu nasıl çözmesi gerektiği konusunda bir açıklama yoktur.
ands

-1

Alternatif olarak, bunun için bir kütüphane de var ..

burada, https://cdnjs.com/libraries/he

npm install he                 //using node.js

<script src="js/he.js"></script>  //or from your javascript directory

Kullanımı aşağıdaki gibidir ...

//to encode text 
he.encode('© Ande & Nonso® Company LImited 2018');  

//to decode the 
he.decode('&copy; Ande &amp; Nonso&reg; Company Limited 2018');

şerefe.


Kütüphanesi hakkında , basit kod örneği ve kütüphaneyi neden ve ne zaman kullanmanız gerektiği konusunda iyi bir açıklama ile tamamlanmış bir cevap var .
ands

-3

HTML Varlıklarını jQuery ile çözmek için şu işlevi kullanın:

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

Nasıl kullanılır:

JavaScript:

var txtEncoded = "&aacute; &eacute; &iacute; &oacute; &uacute;";
$('#some-id').val(html_entity_decode(txtEncoded));

HTML:

<input id="some-id" type="text" />

-3

En kolay yol, öğelerinize bir sınıf seçici ayarlamak ve ardından aşağıdaki kodu kullanmaktır:

$(function(){
    $('.classSelector').each(function(a, b){
        $(b).html($(b).text());
    });
});

Artık hiçbir şey gerekli!

Bu sorunu yaşadım ve bu net çözümü buldum ve işe yarıyor.


Bu OP'nin sorusuna bir cevap değil. OP, STRING'de HTML varlıklarının kodunu çözmeyi ister, yalnızca bu OP'nin sorununu çözmez, aynı zamanda HTML öğesindeki kaçan HTML varlıklarını, yapılmaması gereken kabul edilmemiş olanlarla değiştirir.
ands

-3

Seçilen çözümün tam tersi olduğunu düşünüyorum.

var decoded = $("<div/>").text(encodedStr).html();
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.