Lolos string HTML dengan jQuery


609

Adakah yang tahu cara mudah menghindari HTML dari string di jQuery ? Saya harus dapat melewati string arbitrer dan membuatnya lolos dengan benar untuk ditampilkan di halaman HTML (mencegah serangan JavaScript / injeksi HTML). Saya yakin mungkin untuk memperluas jQuery untuk melakukan ini, tetapi saya tidak cukup tahu tentang kerangka kerja saat ini untuk mencapai ini.


Lihat juga perf: jsperf.com/...
Christophe

Jawaban:


445

Karena Anda menggunakan jQuery , Anda bisa mengatur textproperti elemen :

// 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
Anda melewatkan titik bahwa Anda harus mengakses $ ("div.someClass"). Html () untuk mengeluarkan versi yang keluar.
Morten Christiansen

16
Ini bukan lintas peramban aman jika string Anda memiliki spasi putih dan \ n \ r \ t karakter di dalamnya
nivcaner

20
@ Travis Ini didokumentasikan di situs web jQuery: "Karena variasi dalam parser HTML di browser yang berbeda, teks yang dikembalikan dapat bervariasi di baris baru dan ruang putih lainnya." api.jquery.com/text
geofflee

3
@mklement jika Anda sudah menggunakan solusi ini, Anda tidak akan memiliki masalah dengan melakukan sesuatu seperti: $(element2).attr("some-attr", $(element1).html());Lihat contoh ini: jsbin.com/atibig/1/edit
travis

16
Ini TIDAK lepas dari tanda kutip dan kutip ganda yang buruk! wonko.com/post/html-escaping
Lior

601

Ada juga solusi dari 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
Perhatikan bahwa, anehnya, 'dipetakan ke entitas dengan format desimal , sedangkan /menggunakan format hex .
mklement0

43
Ini harus menjadi jawaban yang diterima - itu sederhana, efisien, tidak memerlukan dependensi dan melakukan apa yang dimaksudkan tanpa peretasan yang tidak jelas.
lorefnon

6
apa pedoman mengkonversi \nke <br>?
amwinter

2
Berikut ini tautan yang diperbarui ke sumber: github.com/janl/mustache.js/blob/…
mjackson

8
@ amwinter, saya menambahkan skrip di atas dengan menambahkan "\ n": '<br>' ke entitas map dan memperbarui regexp ke / [& <> "'\ /] | [\ n] / g
walv

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

Sumber: http://debuggable.com/posts/encode-html-entities-with-jquery:480f4dd6-13cc-4ce9-8071-4710cbdd56cb


11
Seperti disebutkan dalam jawaban di atas, solusi ini tidak dijamin untuk mempertahankan spasi putih.
geofflee

47
Perlu dicatat bahwa ini tidak melakukan apa pun untuk menghindari kutip tunggal atau ganda. jika Anda berencana untuk memasukkan nilai ke dalam atribut HTML, ini bisa menjadi masalah.
Kip

6
@Kip: @travis menemukan bahwa attr()metode jQuery (setidaknya 1,8.3) melakukan penyandian sendiri, sehingga string yang tidak terenkripsi dapat dikirimkan secara langsung ; mis:$('<div/>').attr('test-attr', '\'Tis "fun" & stuff')[0].outerHTML
mklement0

1
@tarekahf Itu aneh. Versi jQuery apa yang Anda gunakan? Apakah kode contoh berfungsi jika Anda menyalin-menempelkannya kata demi kata? Berfungsi baik dengan jQuery terbaru (3.1.0) di sini: jsbin.com/fazimigayo/1/edit?html,js,console, output (dan seharusnya juga bisa digunakan pada semua versi sebelumnya)
Henrik N

1
@tarekahf $('<div/>')menciptakan divelemen baru yang tidak dilampirkan ke DOM. Jadi itu tidak akan mengubah elemen yang ada. Agak membingungkan bagaimana jQuery menggunakan $()fungsi yang sama untuk menemukan elemen ( $('div')) dan untuk membuatnya, dan untuk beberapa hal lagi selain ... :)
Henrik N

61

Jika Anda melarikan diri ke HTML, hanya ada tiga yang dapat saya pikirkan yang akan sangat diperlukan:

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

Tergantung pada kasus penggunaan Anda, Anda mungkin juga perlu melakukan hal-hal seperti "untuk &quot;. Jika daftarnya cukup besar, saya hanya akan menggunakan array:

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() hanya akan menghindarinya untuk URL, bukan untuk HTML.


13
Ekspresi reguler ini akan menghasilkan hasil yang aneh jika HTML yang bersangkutan sudah lolos dari entitas. Misalnya, keluar dari "Tom & amp; Jerry" akan menghasilkan "Tom & amp; amp; Jerry"
Ryan

12
Silakan gunakan varuntuk mendeklarasikan itemsecara lokal; Lagi pula, jangan gunakan for … inloop sama sekali ketika looping melalui array! Gunakan forloop biasa sebagai gantinya. Oh, dan itu encodeURIComponenttidak escapeURIComponent.
Marcel Korpel

3
Jika Anda bekerja dengan atribut tag, maka Anda juga harus keluar dari tanda kutip dan / atau tanda kutip ganda. Dokumentasi PHP untuk htmlspecialchars berisi daftar konversi yang berguna yang dijalankannya. php.net/htmlspecialchars
geofflee

4
Hanya pengingat yang baik bagi orang-orang baru, jangan gunakan ini jika Anda berniat untuk memiliki karakter non-Inggris di suatu tempat di website Anda ... Jelas ini tidak akan melakukan karena karakter dengan aksen seperti 'é': &eacute; Berikut daftar entitas html, untuk referensi: w3schools.com/tags/ref_entities.asp
LoganWolfer

11
@Ryan: Meskipun ada baiknya menunjukkan bahwa solusi ini tidak menangani string yang sudah dikodekan dengan benar, itu juga tidak bernilai apa pun yang sama berlaku untuk sebagian besar - mungkin semua - solusi pada halaman ini.
mklement0

37

Cukup mudah untuk menggunakan garis bawah:

_.escape(string) 

Underscore adalah pustaka utilitas yang menyediakan banyak fitur yang tidak disediakan oleh js asli. Ada juga lodash yang merupakan API yang sama dengan garis bawah tetapi ditulis ulang agar lebih berkinerja.


36

Saya menulis fungsi kecil kecil yang melakukan ini. Hanya lolos ", &, <dan >(tapi biasanya itu semua Anda perlu pula). Ini sedikit lebih elegan daripada solusi yang diusulkan sebelumnya karena hanya menggunakan satu .replace() untuk melakukan semua konversi. ( EDIT 2: Pengurangan kompleksitas kode menjadikan fungsi lebih kecil dan lebih rapi, jika Anda penasaran dengan kode asli, lihat bagian akhir dari jawaban ini.)

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

Ini Javascript biasa, tidak ada jQuery yang digunakan.

Lolos /dan 'juga

Edit dalam menanggapi komentar mklement .

Fungsi di atas dapat dengan mudah diperluas untuk memasukkan karakter apa pun. Untuk menentukan lebih banyak karakter untuk melarikan diri, cukup masukkan keduanya dalam kelas karakter dalam ekspresi reguler (yaitu di dalam /[...]/g) dan sebagai entri dalam chrobjek. ( EDIT 2: Mempersingkat fungsi ini juga, dengan cara yang sama.)

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

Perhatikan penggunaan di atas &#39;untuk tanda kutip (entitas simbolis &apos;mungkin telah digunakan sebagai gantinya - itu didefinisikan dalam XML, tetapi pada awalnya tidak termasuk dalam spesifikasi HTML dan karenanya mungkin tidak didukung oleh semua browser. Lihat: Artikel Wikipedia tentang penyandian karakter HTML ). Saya juga ingat pernah membaca di suatu tempat yang menggunakan entitas desimal lebih banyak didukung daripada menggunakan heksadesimal, tetapi saya tidak bisa menemukan sumber untuk itu sekarang. (Dan tidak mungkin ada banyak browser di luar sana yang tidak mendukung entitas heksadesimal.)

Catatan: Menambahkan /dan 'ke daftar karakter yang lolos tidak terlalu berguna, karena mereka tidak memiliki arti khusus dalam HTML dan tidak perlu diloloskan.

escapeHtmlFungsi Asli

EDIT 2: Fungsi asli menggunakan variabel ( chr) untuk menyimpan objek yang diperlukan untuk .replace()panggilan balik. Variabel ini juga membutuhkan fungsi anonim tambahan untuk membuat ruang lingkup, membuat fungsi (tidak perlu) sedikit lebih besar dan lebih kompleks.

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

Saya belum menguji versi mana dari dua versi yang lebih cepat. Jika Anda melakukannya, jangan ragu untuk menambahkan info dan tautan di sini.


Terima kasih telah meluangkan waktu, @Zrajm. Poin bagus tentang tidak perlu melarikan diri; tahu mengapa keduanya mustache.jsdan underscore.jsmelakukannya? Berbicara tentang yang terakhir: itu hanya mengenali entitas numerik (mewakili 'dan /'), dalam bentuk heks huruf besar ketika tidak melarikan diri. Dengan demikian, teks lolos mustache.js- yang anehnya menggunakan campuran hex. dan format desimal - tidak akan dihapus dengan benar di underscore.js. Saya bertanya-tanya bagaimana perpustakaan populer lainnya mengatasinya.
mklement0

1
Bentuk hex huruf kecil adalah bentuk yang paling didukung, sehingga (mungkin) adalah bentuk yang harus dikonversi ke perpustakaan . (Tentu saja kedua bentuk harus bekerja ketika mengkonversi dari .) - Apostrof 'memiliki semacam fungsi khusus dalam XML (dan dengan demikian XHTML, saya bayangkan?), Itulah sebabnya XML (tetapi bukan HTML) memiliki entitas bernama &apos;. Tepatnya mengapa atau dengan cara apa itu "dicadangkan" saya tidak tahu. - Garis miring khusus di URL, tetapi itu tidak benar - benar menjamin mereka untuk dimasukkan dalam menghindari HTML (karena penyandian URL adalah sesuatu yang sangat berbeda).
zrajm

Re &apos;: benar: penggunaan aman hanya di XHTML ; langsung dari mulut sumber-sumber - penekanan milikku: "(...) dibaca oleh prosesor HTML yang sesuai , (...) penggunaan & apos; atau referensi entitas kustom mungkin tidak didukung (...)" - dalam praktiknya : browser modern mendukungnya bahkan dalam HTML . Kasus kembali dalam hex hex. (sumber yang sama; penekanan pada saya): "X harus huruf kecil dalam dokumen XML. [...] Hhhh dapat mencampur huruf besar dan kecil, meskipun huruf besar adalah gaya yang biasa ." Membuat kita bertanya-tanya siapa yang memutuskan untuk menyandikan garis miring; mungkin benar-benar hanya kebingungan antara pengkodean URI dan HTML?
mklement0

2
Pikiran akhir: sepertinya pengkodean /tidak diperlukan, tetapi pengkodean 'tampaknya masih berguna untuk menangani case case dengan aman di mana string yang dikodekan digunakan sebagai nilai atribut yang dilampirkan dalam tanda kutip tunggal .
mklement0

Keduanya lambat. Solusi tercepat dengan margin dua digit adalah serangkaian penggantian yang diberikan string, bukan fungsi.
Adam Leggett

34

Saya menyadari betapa terlambatnya saya ke pesta ini, tetapi saya memiliki solusi yang sangat mudah yang tidak memerlukan jQuery.

escaped = new Option(unescaped).innerHTML;

Sunting: Ini tidak luput dari penawaran. Satu-satunya kasus di mana kutipan perlu diloloskan adalah jika konten akan ditempelkan sebaris dengan atribut dalam string HTML. Sulit bagi saya untuk membayangkan kasus di mana melakukan ini akan menjadi desain yang bagus.

Sunting 3: Untuk solusi tercepat, periksa jawaban di atas dari Saram. Yang ini adalah yang terpendek.


Ini tidak mengubah tanda kutip - setidaknya sekarang di Firefox 52.
getsetbro

1
Melarikan diri dari kutipan hanya secara fungsional relevan dalam atribut. Karena kita melarikan diri <dan >, tidak ada manfaatnya untuk lolos dari tanda kutip juga, kecuali maksud dari konten yang dihasilkan adalah untuk masuk ke atribut.
Adam Leggett

31

Ini adalah fungsi JavaScript yang bersih dan jelas. Ini akan keluar dari teks seperti "beberapa <banyak" ke "beberapa & lt; banyak".

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

Setelah tes terakhir yang saya dapat merekomendasikan tercepat dan benar-benar lintas browser yang kompatibel native javascript (DOM) solusi:

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

Jika Anda mengulanginya berkali-kali, Anda bisa melakukannya dengan variabel yang sudah disiapkan:

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

Lihatlah perbandingan kinerja akhir saya ( pertanyaan tumpukan ).


2
Apakah perlu menggunakan dua node? Bagaimana kalau hanya satu:var p = document.createElement('p'); p.textContent = html; return p.innerHTML;
Dan Dascalescu

2
@DanDascalescu: Menurut MDN , textContentfungsi ini hanya didukung oleh Chrome 1+, Firefox 2, IE9, Opera 9.64 dan Safari 3 (dua yang terakhir dijelaskan "mungkin lebih awal"). Dengan demikian akan melanggar klaim OP "sepenuhnya kompatibel dengan browser".
zb226

p.innerText = html; return p.innerHTML
Bekim Bacaj

24

Coba Underscore.string lib, ini berfungsi dengan jQuery.

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

keluaran:

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

20
Pustaka garis bawah utama sekarang memiliki _.escape()fungsi utilitas.
codeape

15

Saya telah meningkatkan contoh mustache.js menambahkan escapeHTML()metode ke objek string.

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

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

Dengan begitu cukup mudah digunakan "Some <text>, more Text&Text".escapeHTML()


Berguna, tetapi juga saya pindah __entityMapke fungsi lingkup lokal. Dan membungkus semua ini menjadiif (typeof String.prototype.escapeHTML !== 'function'){...}
FlameStorm

15

escape()dan unescape()dimaksudkan untuk menyandikan / mendekodekan string untuk URL, bukan HTML.

Sebenarnya, saya menggunakan cuplikan berikut untuk melakukan trik yang tidak memerlukan kerangka apa pun:

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

Jika Anda akan memiliki "s maka Anda harus menambahkan setidaknya 'dan `` ke medan. Itu hanya benar-benar diperlukan untuk data tag string di dalam elemen dalam html. Untuk data html itu sendiri (tag luar) hanya 3 yang pertama diperlukan.
Marius

10

Jika Anda memiliki underscore.js, gunakan _.escape(lebih efisien daripada metode jQuery yang diposting di atas):

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

5

Jika Anda menggunakan rute regex, ada kesalahan dalam contoh tghw di atas.

<!-- 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
Saya percaya itu seharusnya untuk (item var di findReplace) {escaped = escaped.replace (findReplace [item] [0], findReplace [item] [1]); }
Chris Stephens

5

Ini adalah contoh aman yang bagus ...

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
Jenis pengecualian apa yang Anda tekan di sana?
Stefan Majewsky

3

Anda dapat dengan mudah melakukannya dengan vanilla js.

Cukup tambahkan simpul teks pada dokumen. Itu akan lolos oleh browser.

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

Tidak ada variabel global, beberapa optimasi memori. Pemakaian:

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

hasilnya adalah:

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

2

2 metode sederhana yang tidak memerlukan JQUERY ...

Anda dapat menyandikan semua karakter di string Anda seperti ini:

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

Atau hanya menargetkan karakter utama perlu khawatir &, jeda baris, <, >, "dan 'seperti:

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

Contoh JavaScript polos yang lolos:

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
Jawaban khusus kode tidak disarankan karena tidak menjelaskan bagaimana mereka menyelesaikan masalah. Harap perbarui jawaban Anda untuk menjelaskan bagaimana ini meningkatkan jawaban yang diterima dan tervvotifikasi dari pertanyaan lain yang sudah ada. Selain itu, pertanyaan ini berusia 9 tahun, usaha Anda akan lebih dihargai oleh pengguna yang memiliki pertanyaan yang belum terjawab baru-baru ini. Harap tinjau Bagaimana cara menulis jawaban yang baik .
FluffyKitten

1
@FluffyKitten di sini adalah posting blog yang ditulis dengan sangat baik tentang kelebihan dan kekurangan dari fungsi tersebut yang menjelaskan secara terperinci semua yang ingin Anda ketahui :) shebang.brandonmintern.com/…
db306

@ db306 Jawabannya ditandai dengan kualitas rendah karena jawaban hanya kode tidak memenuhi pedoman Stack Overflow - lihat Cara menulis jawaban yang bagus . Komentar saya ditambahkan selama proses peninjauan untuk menjelaskan apa yang diperlukan untuk memperbaikinya, yaitu jawabannya perlu diperbarui untuk menjelaskan apa yang dilakukan kode dan bagaimana meningkatkannya pada jawaban yang ada. Upvotes berasal dari pengulas lain untuk mendukung ini. Menambahkan tautan eksternal ke komentar masih belum memenuhi pedoman SO. Sebaliknya Andrew perlu memasukkan informasi yang relevan secara langsung dalam jawabannya.
FluffyKitten

Perhatikan bahwa brandonmintern DOT com telah kedaluwarsa dan sekarang diparkir. Alamat shebang baru adalah shebang.mintern.net/foolproof-html-escaping-in-javascript/.
Brandon

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

bekerja seperti pesona


teks menghapus tag html, tetapi $ ('<div />'). html (t) .html (); bekerja
Bass Jobsen

0

Jawaban ini memberikan metode jQuery dan JS normal, tapi ini yang terpendek tanpa menggunakan DOM:

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

String yang lolos: It%27s%20%3E%2020%25%20less%20complicated%20this%20way.

Jika ruang yang terlepas mengganggu Anda, cobalah:

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

String yang lolos: It%27s %3E 20%25 less complicated this way.

Sayangnya, escape()fungsi tersebut tidak digunakan lagi dalam JavaScript versi 1.5 . encodeURI()atau encodeURIComponent()alternatif, tetapi mereka abaikan ', sehingga baris kode terakhir akan berubah menjadi ini:

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

Semua browser utama masih mendukung kode pendek, dan mengingat jumlah situs web lama, saya ragu itu akan segera berubah.


Ini untuk pengodean URL. Pertanyaannya adalah tentang pelolosan HTML, yang sangat berbeda.
thelem

@ them, tidak jika string tertanam dalam array JavaScript yang tertanam dalam HTML, tapi saya setuju itu tentang HTML biasa yang lolos sehingga dapat segera ditampilkan sebagai teks.
Cees Timmerman

0

ES6 satu liner untuk solusi dari mustache.js

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

-2

Jika Anda menyimpan informasi ini dalam database , itu salah untuk melarikan diri HTML menggunakan skrip sisi klien , ini harus dilakukan di server . Kalau tidak mudah untuk memotong perlindungan XSS Anda.

Untuk memperjelas poin saya, berikut adalah contoh menggunakan salah satu jawaban:

Katakanlah Anda menggunakan fungsi escapeHtml untuk menghindari Html dari komentar di blog Anda dan kemudian mempostingnya ke server Anda.

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

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

Pengguna bisa:

  • Edit parameter permintaan POST dan ganti komentar dengan kode javascript.
  • Timpa fungsi escapeHtml menggunakan konsol browser.

Jika pengguna menempelkan snippet ini di konsol, ia akan mem-bypass validasi XSS:

function escapeHtml(string){
   return string
}

Saya tidak setuju. Untuk melewati perlindungan XSS ini Anda harus menggunakan serangan XSS (menyuntikkan skrip yang menonaktifkan pelarian), yang sebenarnya Anda blokir. Dalam kasus tertentu sebenarnya lebih tepat untuk melarikan diri pada klien, misalnya jika data berasal dari API REST yang harus mengembalikan JSON standar.
ItalyPaleAle

@Qualcuno Jika Anda melakukan validasi ini di klien dan memposting informasi ini ke server yang mempercayai itu divalidasi, pengguna dapat mengedit permintaan dan skrip akan disimpan dalam database.
Kauê Gimenes

@Qualcuno Saya menyertakan beberapa contoh untuk membuat poin saya lebih jelas.
Kauê Gimenes

1
Pertanyaannya adalah tentang melarikan diri string yang diterima dari server untuk menampilkannya di browser. Apa yang Anda katakan adalah tentang melarikan diri string sebelum mengirimkannya ke server, yang merupakan hal yang berbeda (meskipun Anda benar, di sana, dan itu kembali ke aturan lama tidak pernah secara membuta menerima input dari klien )
ItalyPaleAle

@Qualcuno Ini adalah pertanyaan populer di Stackoverflow, dan saya percaya ini adalah poin penting untuk dibahas. Itu sebabnya saya menjawab.
Kauê Gimenes

-2

Semua solusi tidak berguna jika Anda tidak mencegah melarikan diri kembali, mis. Sebagian besar solusi akan terus melarikan diri &ke &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
Itu disebut pelarian ganda dan harus diperbaiki dengan memastikan data input Anda belum lolos. Bagaimana jika Anda ingin benar-benar menunjukkan & lt; kepada pengguna? Atau mungkin teks akan digunakan kembali di tempat lain, dan tergantung pada pelarian yang terjadi?
thelem
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.