Javascript html özel karakter kaçabilir miyim?


202

Bir javascript işlevi tarafından HTML metin görüntülemek istiyorum. JS'de html özel karakterlerinden nasıl kaçabilirim? Bir API var mı?


11
Bu soru jQuery hakkında soru sormadığından bu bir kopya değildir. Ben sadece bu bir ilgileniyorum, çünkü jQuery kullanmıyorum ...
lvella

Yanıtlar:


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

11
Neden "& # 039;" ve "& apos;" değil ?
sereda


2
replace()Çağrılarda düzenli ifadelerin gereksiz olduğunu düşünüyorum . Sade eski tek karakterli dizeler de aynı şeyi yapardı.
jamix

22
@jamix Ham dizelerle küresel bir değişiklik yapamazsınız, modern tarayıcı motorları ise basit düzenli ifadeyi oldukça iyi optimize eder.
bjornd

5
herhangi bir standart API var mı ya da tek yolu bu mu?
Sunil Garg

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


Burada çalışıyor ancak tarayıcıda benim için çevrimdışı çalışmıyor

47

JQuery .text()işlevini kullanabilirsiniz .

Örneğin:

http://jsfiddle.net/9H6Ch/

İşlevle ilgili jQuery belgelerinden .text():

HTML'de doğru şekilde görüntülenmesi için bu yöntemin gerektiği şekilde sağlanan dizeden kaçtığını bilmemiz gerekir. Bunu yapmak için .createTextNode () DOM yöntemini çağırır, dizeyi HTML olarak yorumlamaz.

JQuery Belgelerinin Önceki Sürümleri bunu şu şekilde ifade etmiştir ( vurgu eklenmiştir ):

HTML'de doğru şekilde görüntülenmesi için bu yöntemin gerektiği şekilde sağlanan dizeden kaçtığını bilmemiz gerekir. Bunu yapmak için, özel karakterleri HTML varlık eşdeğerleriyle (<için <<) değiştiren DOM .createTextNode () yöntemini çağırır .


3
Sadece bu şekilde dönüştürmek istiyorsanız taze bir öğe üzerinde bile kullanabilirsiniz: const str = "foo<>'\"&"; $('<div>').text(str).html()verimlerfoo&lt;&gt;'"&amp;
amoebe

28

Sanırım bunu yapmanın doğru yolunu buldum ...

// 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);

Bugün HTML hakkında yeni bir şey öğrendim. w3schools.com/jsref/met_document_createtextnode.asp .
Sellorio

1
Bu şekilde erişmeye çalışırsanız metin düğümünün içeriğinin kaçmadığını unutmayın:document.createTextNode("<script>alert('Attack!')</script>").textContent
maechler

Yaptığınız tek şey metin ayarlamaksa doğru yol budur. Bu aynı zamanda textContent ama görünüşe göre iyi desteklenmiyor. Ancak bu, bazı bölümleri bazı html metinleri içeren bir dize oluşturuyorsanız, o zaman yine de kaçmanız gerekir.
jgmjgm


21

Bu, şimdiye kadar, bunu yapmanın en hızlı yolu. Ayrıca, sayfadaki öğeleri eklemeden, çıkarmadan veya değiştirmeden hepsini yapar.

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

7
Uyarı: Bu vermez HTML kodunda çıktı içeride özellik değerlerini kullanamaması için tırnak kaçış. Örneğin var divCode = '<div data-title="' + escapeHTML('Jerry "Bull" Winston') + '">Div content</div>'geçersiz HTML verir!
izogfif

17

Daha iyi bir çözüm bulmak ilginçti:

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

>Sonuçta XML / HTML kodunu bozmadığı için ayrıştırmadım .

İşte kriterler: http://jsperf.com/regexpairs Ayrıca, evrensel bir escapeişlev oluşturdum : http://jsperf.com/regexpairs2


1
Anahtarı kullanmanın haritadan çok daha hızlı olduğunu görmek ilginç. Bunu beklemiyordum! Paylaşım için teşekkürler!
Peter T.

Olası kodlama ve dikkate alabileceğinizden çok daha fazla unicode karakter var. Bu manuel yöntemi hiç tavsiye etmem.
vsync

Neden çok baytlık karakterlerden kaçasınız ki? Sadece her yerde UTF-8 kullanın.
Neonit

4
Atlama> kodun kırılmasına neden olabilir. <> İçinde de html olduğunu unutmayın. Bu durumda atlama> kırılacaktır. Yalnızca etiketler arasında kaçıyorsanız, muhtemelen sadece <ve & karakterinden kaçmanız gerekir.
jgmjgm

8

Kodlanmamış metni görüntülemenin en özlü ve en etkili yolu textContentözelliği kullanmaktır .

Kullanmaktan daha hızlıinnerHTML . Ve bu yükten kaçmayı hesaba katmadan.

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


@ZzZombo, stil ve komut dosyası etiketleri ile çalışmaması normaldir. Onlara içerik eklediğinizde , metin değil kod eklersiniz , bu durumda innerHTML kullanın. Dahası, bundan kaçmanıza gerek yok, bunlar HTML olarak ayrıştırılmayan iki özel etiket. Ayrıştırma sırasında, içerikleri, kapanış sırası karşılanana kadar metin olarak kabul edilir . </
kullanıcı

6

DOM Elements, innerText öğesine atayarak metni HTML'ye dönüştürmeyi destekler . innerText bir işlev değildir, ancak atanması metin kaçmış gibi çalışır.

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

1
En azından Chrome'da çok satırlı metin atamak <br>, satırlar yerine stiller veya komut dosyaları gibi belirli öğeleri kırabilecek öğeler ekler . createTextNodeBu sorunun eğilimli değildir.
ZzZombo

1
innerTextbazı eski / spesifikasyon sorunları var. Kullanmak daha iyi textContent.
Roy Tinker

3

Dizenizdeki her karakteri kodlayabilirsiniz:

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

Veya endişelenmeniz gereken ana karakterleri hedefleyin (&, inebreaks, <,>, "ve '):

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>


Kendi kaçış fonksiyonunuzu yazmak genellikle kötü bir fikirdir. Diğer cevaplar bu konuda daha iyidir.
jannis

2

Bir astar (ES6 + için):

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

Eski sürümler için:

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

0

Bir DOM yapısı oluştururken bu sorunla karşılaştım. Bu soru çözmeme yardımcı oldu. Bir yol ayırıcı olarak çift chevron kullanmak istedim, ancak yeni bir metin düğümü eklemek doğrudan karakterin kendisi yerine kaçan karakter kodu ile sonuçlandı:

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

Uygulamanızda zaten modüller kullanıyorsanız, escape-html modülünü kullanabilirsiniz.

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


-4

Bu çözümü buldum.

Kullanıcıya veya veritabanından güvenli olmayan veriler içeren öğeye bazı html eklemek istediğimizi varsayalım.

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 saldırılarına karşı güvenli değil. Şimdi bunu ekleyin.

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

İşte bu

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

Bana göre bu kullanmaktan çok daha kolay .replace()ve kaldırılacak !!! tüm olası html etiketleri (umarım).


bu tehlikeli bir fikirdir, güvensiz HTML Dizesini HTML olarak ayrıştırır, öğe DOM'ye eklenmişse exeute olur. bunun yerine .innerText kullanın.
teknopaul

Bu güvenli değil. Bu dönüştürür &lt;script&gt;içine <script>.
fgb
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.