การหลบหนีสตริง HTML ด้วย jQuery


609

ไม่มีใครรู้วิธีง่ายๆในการหลีกเลี่ยง HTML จากสตริงในjQuery ? ฉันต้องสามารถส่งผ่านสตริงที่กำหนดเองและนำไปใช้อย่างถูกต้องเพื่อแสดงในหน้า HTML (ป้องกันการโจมตีด้วยการฉีด JavaScript / HTML) ฉันแน่ใจว่าเป็นไปได้ที่จะขยาย jQuery ให้ทำเช่นนี้ แต่ฉันไม่รู้เกี่ยวกับกรอบในขณะนี้เพื่อให้บรรลุนี้


โปรดดู perf: jsperf.com/ ด้วย
Christophe Roussy

คำตอบ:


445

เนื่องจากคุณใช้jQueryคุณสามารถตั้งค่าtextคุณสมบัติขององค์ประกอบได้:

// 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
คุณพลาดจุดที่คุณต้องเข้าถึง $ ("div.someClass"). html () เพื่อรับรุ่นที่ใช้ Escape
มอร์เทนคริสเตียน

16
นี่ไม่ได้ข้ามเบราว์เซอร์ที่ปลอดภัยหากสตริงของคุณมีช่องว่างและ \ n \ r \ t ตัวอักษรอยู่ในนั้น
nivcaner

20
@travis เอกสารนี้มีไว้ในเว็บไซต์ jQuery: "เนื่องจากรูปแบบต่างๆในตัวแยกวิเคราะห์ HTML ในเบราว์เซอร์ที่แตกต่างกันข้อความที่ส่งคืนอาจแตกต่างกันไปขึ้นบรรทัดใหม่และพื้นที่สีขาวอื่น ๆ " api.jquery.com/text
geofflee

3
@mklement หากคุณใช้โซลูชันนี้อยู่แล้วคุณจะไม่มีปัญหากับสิ่งที่ทำเช่น: $(element2).attr("some-attr", $(element1).html());ดูตัวอย่างนี้: jsbin.com/atibig/1/edit
travis

16
นี่ไม่ได้หนีเครื่องหมายอัญประกาศและเครื่องหมายคำพูดคู่ซึ่งไม่ดี! wonko.com/post/html-escaping
Lior

601

นอกจากนี้ยังมีทางออกจาก 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
โปรดทราบว่าอยากรู้อยากเห็น'ถูกจับคู่กับนิติบุคคลที่มีทศนิยมรูปแบบในขณะที่/การนำมาใช้ประโยชน์ฐานสิบหกรูปแบบ
mklement0

43
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ - มันง่ายมีประสิทธิภาพไม่จำเป็นต้องพึ่งพาและทำในสิ่งที่ตั้งใจไว้โดยไม่มีแฮ็กที่คลุมเครือ
lorefnon

6
คำแนะนำในการแปลง\nเป็น<br>อย่างไร
amwinter

2
นี่คือลิงก์ที่อัปเดตไปยังแหล่งข้อมูล: github.com/janl/mustache.js/blob/…
mjackson

8
@amwinter ฉันขยายสคริปต์ด้านบนเพิ่ม "\ n": '<br>' ลงในแผนที่เอนทิตีและอัปเดต regexp เป็น / [& <> "'\ /] | [\ n] / g
walv

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

ที่มา: http://debuggable.com/posts/encode-html-entities-with-jquery:480f4dd6-13cc-4ce9-8071-4710cbdd56cb


11
ดังที่ได้กล่าวไว้ในคำตอบข้างต้นโซลูชันนี้ไม่รับประกันว่าจะรักษาช่องว่าง
geofflee

47
มันควรจะสังเกตว่ามันไม่ทำอะไรเลยที่จะหลบหนีคำพูดเดียวหรือสองครั้ง หากคุณวางแผนที่จะใส่ค่าลงในแอตทริบิวต์ HTML สิ่งนี้อาจเป็นปัญหาได้
Kip

6
@Kip: @travis พบว่าของ jQuery attr()วิธี (เป็นอย่างน้อย 1.8.3) ไม่เข้ารหัสของตัวเองเพื่อให้สตริง unencoded สามารถส่งผ่านโดยตรง ; เช่น:$('<div/>').attr('test-attr', '\'Tis "fun" & stuff')[0].outerHTML
mklement0

1
@tarekahf มันแปลกมาก คุณใช้ jQuery รุ่นใดอยู่ โค้ดตัวอย่างใช้งานได้หรือไม่หากคุณคัดลอกวางเป็นคำต่อคำ? ใช้งานได้ดีกับ jQuery ล่าสุด (3.1.0) ที่นี่: jsbin.com/fazimigayo/1/edit?html,js,console,output (และควรทำงานกับเวอร์ชันก่อนหน้าทั้งหมดด้วย)
Henrik N

1
@tarekahf $('<div/>')สร้างdivองค์ประกอบใหม่ที่ไม่ได้แนบกับ DOM ดังนั้นมันจะไม่เปลี่ยนแปลงองค์ประกอบใด ๆ ที่มีอยู่ มันค่อนข้างสับสนว่า jQuery ใช้$()ฟังก์ชั่นเดียวกันทั้งคู่เพื่อค้นหาองค์ประกอบ ( $('div')) และสร้างมันและอีกสองสามอย่างนอกเหนือจาก… :)
Henrik N

61

หากคุณกำลังหลบหนีสำหรับ HTML มีเพียงสามที่ฉันสามารถคิดว่าจะมีความจำเป็นจริงๆ:

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

ทั้งนี้ขึ้นอยู่กับกรณีการใช้งานของคุณคุณยังอาจจำเป็นต้องทำสิ่งที่ต้องการที่จะ" &quot;หากรายการมีขนาดใหญ่พอฉันจะใช้อาร์เรย์:

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() จะยกเว้นเฉพาะ URL เท่านั้นไม่ใช่ HTML


13
นิพจน์ทั่วไปนี้จะให้ผลลัพธ์ที่แปลกถ้า HTML ที่เป็นปัญหาได้หลบหนีเอนทิตีไปแล้ว ตัวอย่างเช่นการหลบหนี "Tom & amp; Jerry" จะสร้าง "Tom & amp; amp; Jerry"
Ryan

12
โปรดใช้varเพื่อประกาศitemในท้องถิ่น อย่างไรก็ตามอย่าใช้การfor … inวนซ้ำเลยเมื่อวนผ่านอาร์เรย์! ใช้การforวนซ้ำธรรมดาแทน โอ้และก็ไม่ได้encodeURIComponent escapeURIComponent
Marcel Korpel

3
หากคุณกำลังทำงานกับแอตทริบิวต์แท็กคุณจะต้องหลีกเลี่ยงอัญประกาศและ / หรือเครื่องหมายคำพูดคู่ เอกสารประกอบ PHP สำหรับ htmlspecialchars มีรายการการแปลงที่มีประโยชน์php.net/htmlspecialchars
geofflee

4
เพียงแค่เตือนชนิดสำหรับคนใหม่ไม่ได้ใช้นี้ถ้าคุณตั้งใจจะมีตัวละครที่ไม่ใช่ภาษาอังกฤษที่ไหนสักแห่งบนเว็บไซต์ของคุณ ... เห็นได้ชัดว่านี้จะไม่ทำเพราะของตัวละครด้วยสำเนียงเช่น 'E': &eacute; นี่คือรายการเอนทิตี html สำหรับการอ้างอิง: w3schools.com/tags/ref_entities.asp
LoganWolfer

11
@Ryan: ในขณะที่มันมีค่าชี้ให้เห็นว่าวิธีการแก้ปัญหานี้ไม่ได้จัดการสายอักขระที่เข้ารหัสแล้วอย่างถูกต้อง แต่ก็ไม่มีอะไรที่คุ้มค่าเหมือนกันกับส่วนใหญ่ - อาจทั้งหมด - โซลูชั่นในหน้านี้
mklement0

37

ง่ายพอที่จะใช้ขีดเส้นใต้:

_.escape(string) 

ขีดเป็นไลบรารียูทิลิตี้ที่มีคุณสมบัติมากมายที่ Native js ไม่มีให้ นอกจากนี้ยังมีlodashซึ่งเป็น API เดียวกับขีดล่าง แต่ถูกเขียนใหม่เพื่อให้มีประสิทธิภาพมากขึ้น


36

ฉันเขียนฟังก์ชั่นเล็ก ๆ ซึ่งทำสิ่งนี้ มันหนี", &, <และ>( แต่มักนั่นคือทั้งหมดที่คุณต้องการอยู่แล้ว) มันมีความสง่างามกว่าเล็กน้อยจากนั้นโซลูชันที่นำเสนอก่อนหน้านี้จะใช้วิธีเดียว .replace()ในการทำ Conversion ทั้งหมด ( แก้ไข 2:ความซับซ้อนของรหัสที่ลดลงทำให้ฟังก์ชั่นมีขนาดเล็กลงและน้อยลงหากคุณสงสัยเกี่ยวกับรหัสต้นฉบับดูที่ส่วนท้ายของคำตอบนี้)

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

นี่คือ Javascript ธรรมดาไม่มีการใช้ jQuery

หลบหนี/และ'เกินไป

แก้ไขเพื่อตอบสนองต่อความคิดเห็นของmklement

ฟังก์ชั่นด้านบนสามารถขยายได้อย่างง่ายดายเพื่อรวมอักขระใด ๆ ในการระบุตัวละครที่จะหลบหนีให้มากขึ้นเพียงแค่ใส่ทั้งสองในคลาสตัวละครในนิพจน์ปกติ (เช่นภายใน/[...]/g) และเป็นรายการในchrวัตถุ ( แก้ไข 2:ย่อฟังก์ชั่นนี้ด้วยวิธีเดียวกัน)

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

โปรดสังเกตการใช้&#39;apostrophe ด้านบน(เอนทิตีสัญลักษณ์&apos;อาจถูกใช้แทน - ถูกกำหนดใน XML แต่เดิมไม่รวมอยู่ในข้อมูลจำเพาะ HTML และเบราว์เซอร์ทั้งหมดอาจไม่รองรับดังนั้นโปรดดู: บทความ Wikipedia เกี่ยวกับการเข้ารหัสอักขระ HTML ) ฉันยังจำการอ่านบางที่ว่าการใช้หน่วยงานทศนิยมได้รับการสนับสนุนอย่างกว้างขวางมากกว่าการใช้เลขฐานสิบหก แต่ฉันไม่สามารถหาแหล่งที่มาได้ในขณะนี้ (และไม่สามารถมีเบราว์เซอร์จำนวนมากที่ไม่สนับสนุนเอนทิตีเลขฐานสิบหก)

หมายเหตุ: การเพิ่ม/และ'ไปยังรายการของอักขระที่ใช้ Escape นั้นไม่ใช่สิ่งที่มีประโยชน์ทั้งหมดเนื่องจากไม่มีความหมายพิเศษใน HTML และไม่จำเป็นต้องใช้ Escape

escapeHtmlฟังก์ชั่นดั้งเดิม

แก้ไข 2:ฟังก์ชั่นเดิมใช้ตัวแปร ( chr) เพื่อเก็บวัตถุที่จำเป็นสำหรับการ.replace()โทรกลับ ตัวแปรนี้ต้องการฟังก์ชันที่ไม่ระบุชื่อพิเศษเพื่อกำหนดขอบเขตทำให้ฟังก์ชัน (โดยไม่จำเป็น) ใหญ่ขึ้นและซับซ้อนขึ้นเล็กน้อย

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

ฉันยังไม่ได้ทดสอบเวอร์ชันใดในสองเวอร์ชันที่เร็วกว่า ถ้าเป็นเช่นนั้นคุณสามารถเพิ่มข้อมูลและลิงค์เกี่ยวกับมันได้ที่นี่


ขอบคุณที่สละเวลา @Zrajm ข้อดีคือไม่ต้องหลบหนี คิดว่าทำไมทั้งสองmustache.jsและunderscore.jsทำมันได้หรือไม่ การพูดของหลัง: มันจำได้เฉพาะหน่วยงานที่เป็นตัวเลข (แทน'และ/') ในรูปแบบเลขฐานสิบหกตัวพิมพ์ใหญ่เมื่อไม่หนี ดังนั้นข้อความที่หลบหนีmustache.js- ซึ่งใช้การผสมผสานของฐานสิบหก และรูปแบบทศนิยม - จะไม่ได้ใช้ Escape underscore.jsอย่างถูกต้องใน ฉันสงสัยว่าห้องสมุดยอดนิยมอื่น ๆ จัดการกับเรื่องนี้อย่างไร
mklement0

1
รูปแบบกรณีฐานสิบหกล่างเป็นรูปแบบที่ได้รับการสนับสนุนมากที่สุดเพื่อให้เป็น (อาจ) แบบฟอร์มที่ห้องสมุดควรแปลงไป (แน่นอนทั้งสองรูปแบบควรจะทำงานเมื่อมีการแปลงจาก .) - Apostrophes 'มีการจัดเรียงของฟังก์ชั่นที่สงวนไว้ในรูปแบบ XML บางส่วนซึ่งเป็นเหตุผลที่ XML ( แต่ไม่ HTML) &apos;มีชื่อนิติบุคคล ในสิ่งที่ว่าทำไมหรือในวิธีการที่ "จอง" ฉันไม่รู้ - Slashes เป็นพิเศษใน URL ที่ แต่ที่ไม่จริงรับประกันพวกเขาสำหรับการรวมในการหลบหนี HTML (ตามการเข้ารหัส URL เป็นสิ่งที่แตกต่างอย่างสิ้นเชิง)
zrajm

ตอบ&apos;: ถูกต้อง: ใช้อย่างปลอดภัยในXHTMLเท่านั้น ตรงจากปากของฝูงชนที่มา - เหมืองเน้น: "(... ) อ่านโดยหน่วยประมวลผลHTML ที่สอดคล้องกัน(... ) ใช้ & apos; หรือการอ้างอิงเอนทิตีที่กำหนดเองอาจไม่ได้รับการสนับสนุน (... )" - ในทางปฏิบัติ : เบราว์เซอร์ที่ทันสมัยสนับสนุนแม้ในHTML กรณีในจำนวน hex (แหล่งเดียวกัน; การเน้นของฉัน): "x ต้องเป็นตัวพิมพ์เล็กในเอกสาร XML [... ] hhhh อาจผสมตัวพิมพ์ใหญ่และตัวพิมพ์เล็กแม้ว่าตัวพิมพ์ใหญ่จะเป็นสไตล์ปกติ " ทำให้เราสงสัยว่าใครเป็นคนตัดสินใจเข้ารหัสสแลช บางทีอาจเป็นเพียงความสับสนระหว่างการเข้ารหัส URI และ HTML
mklement0

2
ความคิดสุดท้าย: ดูเหมือนว่าการเข้ารหัส/ไม่จำเป็น แต่การเข้ารหัส'ยังดูเหมือนว่ามีประโยชน์ในการจัดการกับกรณีกรณีที่สตริงเข้ารหัสใช้เป็นอย่างปลอดภัยแอตทริบิวต์ค่าล้อมรอบในราคาเดียว
mklement0

ทั้งสองอย่างนี้ช้า การแก้ปัญหาที่เร็วที่สุดโดยส่วนต่างเลขสองหลักคือชุดของการแทนที่ที่ส่งผ่านสตริงแทนฟังก์ชั่น
Adam Leggett

34

ฉันรู้ว่าฉันมางานปาร์ตี้ช้าแค่ไหน แต่ฉันมีทางออกที่ง่ายมากที่ไม่ต้องใช้ jQuery

escaped = new Option(unescaped).innerHTML;

แก้ไข: นี่ไม่ได้หนีคำพูด กรณีเดียวที่ต้องหลีกเลี่ยงการเสนอราคาคือถ้าเนื้อหาจะถูกวางแบบอินไลน์ไปยังแอตทริบิวต์ภายในสตริง HTML มันยากสำหรับฉันที่จะจินตนาการถึงกรณีที่การทำเช่นนี้จะเป็นการออกแบบที่ดี

แก้ไข 3: สำหรับวิธีที่เร็วที่สุดตรวจสอบคำตอบข้างต้นจาก Saram อันนี้สั้นที่สุด


สิ่งนี้ไม่เปลี่ยนราคา - อย่างน้อยตอนนี้ใน Firefox 52
getetbro

1
การเสนอราคาจะเกี่ยวข้องเฉพาะกับคุณสมบัติในแอททริบิวต์เท่านั้น เนื่องจากเรากำลังหลบหนี<และ>ไม่มีประโยชน์ที่จะหลบหนีคำพูดด้วยเช่นกันเว้นแต่ว่าเจตนาของเนื้อหาที่สร้างขึ้นคือการเข้าสู่แอตทริบิวต์
Adam Leggett

31

นี่คือฟังก์ชัน JavaScript ที่ชัดเจนและชัดเจน มันจะหนีจากข้อความเช่น "<<น้อยมาก" ไปยัง "ไม่กี่ & lt; หลาย"

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

หลังจากการทดสอบครั้งล่าสุดฉันสามารถแนะนำวิธีแก้ปัญหาnative javaScript (DOM) ที่เข้ากันได้กับเบราว์เซอร์ได้อย่างรวดเร็วและสมบูรณ์แบบ:

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

หากคุณทำซ้ำหลาย ๆ ครั้งคุณสามารถทำได้ด้วยตัวแปรที่เตรียมไว้ครั้งเดียว:

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

ดูการเปรียบเทียบประสิทธิภาพสุดท้ายของฉัน( คำถามสแต็ค )


2
จำเป็นต้องใช้สองโหนดหรือไม่ วิธีการเกี่ยวกับเพียงหนึ่ง:var p = document.createElement('p'); p.textContent = html; return p.innerHTML;
แดนดาสคเลสุ

2
@DanDascalescu: ตามMDNที่textContentฟังก์ชั่นได้รับการสนับสนุนโดย Chrome 1+, Firefox 2, IE9, Opera และ Safari 9.64 3 เท่านั้น (หลังสองข้อเขียน "อาจจะเป็นก่อนหน้านี้") มันจะทำลายการอ้างสิทธิ์ "เข้ากันได้ข้ามเบราว์เซอร์" อย่างสมบูรณ์
zb226

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

24

ลองUnderscore.string lib มันใช้งานได้กับ jQuery

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

เอาท์พุท:

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

20
ขณะนี้ไลบรารีขีดล่างหลักมี_.escape()ฟังก์ชันยูทิลิตี้
codeape

15

ฉันได้ปรับปรุงตัวอย่าง mustache.js การเพิ่มescapeHTML()วิธีการไปยังวัตถุสตริง

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

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

ด้วยวิธีนี้มันค่อนข้างใช้งานง่าย "Some <text>, more Text&Text".escapeHTML()


มีประโยชน์ แต่ฉันก็ย้าย__entityMapเข้าสู่ฟังก์ชั่นขอบเขตท้องถิ่น และรวบรวมสิ่งทั้งหมดนี้ไว้ในif (typeof String.prototype.escapeHTML !== 'function'){...}
FlameStorm

15

escape()และunescape()มีวัตถุประสงค์เพื่อเข้ารหัส / ถอดรหัสสตริงสำหรับ URL ไม่ใช่ HTML

ที่จริงแล้วฉันใช้ตัวอย่างต่อไปนี้เพื่อทำเคล็ดลับที่ไม่ต้องการกรอบใด ๆ :

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

หากคุณกำลังจะมี"แล้วคุณต้องเพิ่มอย่างน้อย'และ `` การต่อสู้ สิ่งเหล่านี้จำเป็นสำหรับข้อมูลแท็กสตริงภายในองค์ประกอบใน html เท่านั้น สำหรับข้อมูล html (แท็กภายนอก) จะต้องมี 3 รายการแรกเท่านั้น
Marius

10

หากคุณมี underscore.js ให้ใช้_.escape(มีประสิทธิภาพมากกว่าวิธี jQuery ที่โพสต์ด้านบน):

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

5

หากคุณกำลังจะไปเส้นทาง regex มีข้อผิดพลาดในตัวอย่างของ 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]]);
}

2
ฉันเชื่อว่าควรใช้สำหรับ (รายการ var ใน findReplace) {escaped = escaped.replace (findReplace [รายการ] [0], findReplace [รายการ] [1]); }
Chris Stephens

5

นี่เป็นตัวอย่างที่ปลอดภัยที่ดี ...

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
คุณมีข้อยกเว้นประเภทใด
Stefan Majewsky

3

คุณสามารถทำได้ด้วยวานิลลา js

เพียงเพิ่มเอกสารข้อความในโหนด มันจะถูกเบราว์เซอร์หลบหนี

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

ไม่มีตัวแปรส่วนกลาง, การเพิ่มประสิทธิภาพหน่วยความจำบางส่วน การใช้งาน:

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

ผลลัพธ์คือ:

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

2

2 วิธีการง่าย ๆ ที่ไม่ต้องมี JQUERY ...

คุณสามารถเข้ารหัสอักขระทั้งหมดในสตริงของคุณดังนี้:

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

หรือเพียงแค่กำหนดเป้าหมายตัวละครหลักที่จะต้องกังวลเกี่ยวกับการ&แบ่งบรรทัด<, >, "และ'ที่ชอบ:

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

ตัวอย่างการหลีกเลี่ยง 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;"

3
คำตอบที่เป็นรหัสเท่านั้นจะหมดกำลังใจเพราะพวกเขาไม่ได้อธิบายวิธีที่พวกเขาแก้ไขปัญหา โปรดอัปเดตคำตอบของคุณเพื่ออธิบายว่าสิ่งนี้ดีขึ้นอย่างไรเมื่อได้รับคำตอบอื่น ๆ และ upvoteแล้วคำถามนี้มีอยู่แล้ว นอกจากนี้คำถามนี้มีอายุ 9 ปีความพยายามของคุณจะได้รับการชื่นชมจากผู้ใช้ที่มีคำถามที่ยังไม่ได้ตอบล่าสุด โปรดตรวจสอบฉันจะเขียนคำตอบที่ดีได้อย่างไร
FluffyKitten

1
@FluffyKitten ที่นี่เป็นบล็อกโพสต์ที่เขียนขึ้นอย่างมากเกี่ยวกับข้อดีและข้อเสียของฟังก์ชั่นดังกล่าวที่อธิบายในรายละเอียดทุกสิ่งที่คุณอยากจะรู้ :) shebang.brandonmintern.com/ …
db306

@ db306 คำตอบที่ได้รับการตั้งค่าสถานะเป็นที่มีคุณภาพต่ำเนื่องจากรหัสเท่านั้นคำตอบที่ไม่ตรงตามหลักเกณฑ์กองมากเกิน - ดูวิธีการเขียนคำตอบที่ดี ความคิดเห็นของฉันถูกเพิ่มในระหว่างกระบวนการตรวจสอบเพื่ออธิบายสิ่งที่จำเป็นในการปรับปรุงคือคำตอบจำเป็นต้องได้รับการอัปเดตเพื่ออธิบายสิ่งที่รหัสทำและวิธีปรับปรุงในคำตอบที่มีอยู่ upvotes นั้นมาจากผู้ตรวจสอบคนอื่น ๆ เพื่อรับรองเรื่องนี้ การเพิ่มลิงก์ภายนอกไปยังความคิดเห็นยังคงไม่เป็นไปตามหลักเกณฑ์ของ SO แอนดรูว์ต้องการที่จะรวมข้อมูลที่เกี่ยวข้องโดยตรงในคำตอบของเขา
FluffyKitten

โปรดทราบว่า brandonmintern DOT com หมดอายุและจอดอยู่ในขณะนี้ ที่อยู่ shebang ใหม่คือ shebang.mintern.net/foolproof-html-escaping-in-javascript/
แบรนดอน

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

ทำงานเหมือนจับใจ


ข้อความจะลบแท็ก html แต่ $ ('<div />'). html (t) .html (); ทำงาน
Bass Jobsen

0

คำตอบนี้ให้ jQuery และวิธีการ JS ปกติ แต่จะสั้นที่สุดโดยไม่ใช้ DOM:

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

สตริงที่หนี: It%27s%20%3E%2020%25%20less%20complicated%20this%20way.

หากช่องว่างที่ถูกรบกวนนั้นรบกวนคุณให้ลอง:

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

สตริงที่หนี: It%27s %3E 20%25 less complicated this way.

แต่น่าเสียดายที่escape()ฟังก์ชั่นได้รับการคัดค้านในรุ่น 1.5 encodeURI()หรือencodeURIComponent()เป็นทางเลือก แต่พวกเขาไม่สนใจ'ดังนั้นรหัสบรรทัดสุดท้ายจะเปลี่ยนเป็น:

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

เบราว์เซอร์หลักทั้งหมดยังคงสนับสนุนรหัสย่อและด้วยจำนวนเว็บไซต์เก่าฉันสงสัยว่าจะเปลี่ยนแปลงเร็ว ๆ นี้


นี่คือการเข้ารหัส URL คำถามเกี่ยวกับการหลบหนี HTML ซึ่งแตกต่างกันมาก
thelem

@thelem ไม่ใช่หากมีการฝังสตริงในอาร์เรย์ JavaScript ที่ฝังอยู่ใน HTML แต่ฉันยอมรับว่ามันเกี่ยวกับการหลบหลีก HTML ธรรมดาดังนั้นจึงสามารถแสดงเป็นข้อความได้ทันที
Cees Timmerman


-2

หากคุณกำลังบันทึกข้อมูลนี้ในฐานข้อมูลผิดที่จะหลบหนี HTML โดยใช้สคริปต์ฝั่งไคลเอ็นต์สิ่งนี้ควรทำในเซิร์ฟเวอร์ มิฉะนั้นจะง่ายต่อการข้ามการป้องกัน XSS ของคุณ

เพื่อให้จุดของฉันชัดเจนนี่คือตัวอย่างโดยใช้หนึ่งในคำตอบ:

สมมติว่าคุณกำลังใช้ฟังก์ชัน escapeHtml เพื่อหลีกเลี่ยง Html จากความคิดเห็นในบล็อกของคุณแล้วโพสต์ลงในเซิร์ฟเวอร์ของคุณ

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

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

ผู้ใช้สามารถ:

  • แก้ไขพารามิเตอร์คำขอ POST และแทนที่ความคิดเห็นด้วยรหัสจาวาสคริปต์
  • เขียนทับฟังก์ชัน escapeHtml โดยใช้คอนโซลของเบราว์เซอร์

หากผู้ใช้วางตัวอย่างนี้ในคอนโซลมันจะผ่านการตรวจสอบ XSS:

function escapeHtml(string){
   return string
}

ฉันไม่เห็นด้วย. ในการหลีกเลี่ยงการป้องกัน XSS นี้คุณจะต้องใช้การโจมตี XSS (การฉีดสคริปต์ที่ปิดใช้งานการหลบหนี) ซึ่งเป็นสิ่งที่คุณกำลังปิดกั้นจริง ๆ ในบางกรณีการหลีกเลี่ยงลูกค้าจะเหมาะสมกว่าตัวอย่างเช่นถ้าข้อมูลมาจาก REST API ที่ต้องส่งคืน JSON มาตรฐาน
ItalyPaleAle

@Qualcuno หากคุณทำการตรวจสอบความถูกต้องนี้ในไคลเอนต์และโพสต์ข้อมูลนี้ไปยังเซิร์ฟเวอร์ที่เชื่อถือได้ว่ามีการตรวจสอบผู้ใช้สามารถแก้ไขการร้องขอและสคริปต์จะถูกบันทึกในฐานข้อมูล
Kauê Gimenes

@Qualcuno ฉันรวมตัวอย่างเพื่อทำให้จุดของฉันชัดเจนยิ่งขึ้น
Kauê Gimenes

1
คำถามเกี่ยวกับการหลีกเลี่ยงสตริงที่ได้รับจากเซิร์ฟเวอร์เพื่อแสดงบนเบราว์เซอร์ สิ่งที่คุณกำลังพูดเกี่ยวกับการหลบหนีสตริงก่อนที่จะส่งพวกเขาไปยังเซิร์ฟเวอร์ซึ่งเป็นสิ่งที่แตกต่างกัน (แม้ว่าคุณจะถูกต้องที่นั่นและมันกลับไปที่กฎเดิมไม่เคยยอมรับการป้อนข้อมูลใด ๆ จากลูกค้า )
ItalyPaleAle

@Qualcuno นี่เป็นคำถามยอดนิยมใน Stackoverflow และฉันเชื่อว่านี่เป็นจุดสำคัญที่จะครอบคลุม นั่นเป็นเหตุผลที่ฉันตอบ
Kauê Gimenes

-2

โซลูชันทั้งหมดไม่มีประโยชน์หากคุณไม่ป้องกันการหลบหนีเช่นโซลูชันส่วนใหญ่จะหนี&ไป&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
นั่นเรียกว่าการหลีกเลี่ยงสองครั้งและควรได้รับการแก้ไขโดยตรวจสอบให้แน่ใจว่าข้อมูลอินพุตของคุณยังไม่ได้หลบหนี จะเป็นอย่างไรถ้าคุณต้องการแสดง & lt; ถึงผู้ใช้? หรือบางทีข้อความจะถูกนำไปใช้ที่อื่นและขึ้นอยู่กับการหลบหนีที่เกิดขึ้น?
thelem
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.