ฉันจะใช้ jQuery เพื่อถอดรหัสเอนทิตี HTML ในสตริงได้อย่างไร
ฉันจะใช้ jQuery เพื่อถอดรหัสเอนทิตี HTML ในสตริงได้อย่างไร
คำตอบ:
หมายเหตุด้านความปลอดภัย: การใช้คำตอบนี้ (เก็บรักษาไว้ในรูปแบบดั้งเดิมด้านล่าง) อาจทำให้เกิดช่องโหว่ XSSในแอปพลิเคชันของคุณ คุณไม่ควรใช้คำตอบนี้ อ่านคำตอบของ lucascaroสำหรับคำอธิบายเกี่ยวกับช่องโหว่ในคำตอบนี้และใช้แนวทางจากทั้งคำตอบนั้นหรือคำตอบของMark Ameryแทน
ที่จริงแล้วลอง
var decoded = $("<div/>").html(encodedStr).text();
$("<div/>").html('<img src="http://www.google.com/images/logos/ps_logo2.png" onload=alert(1337)>')
ลองใช้ ใน Firefox หรือ Safari ไฟจะแจ้งเตือน
str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/g, "")
หรือสิ่งที่คล้ายกัน
ไม่มี jQuery:
function decodeEntities(encodedString) {
var textArea = document.createElement('textarea');
textArea.innerHTML = encodedString;
return textArea.value;
}
console.log(decodeEntities('1 & 2')); // '1 & 2'
วิธีนี้ทำงานคล้ายกับคำตอบที่ยอมรับแต่ปลอดภัยที่จะใช้กับอินพุตของผู้ใช้ที่ไม่น่าเชื่อถือ
ตามที่ระบุไว้โดย Mike Samuelการทำเช่นนี้<div>
แทนการ<textarea>
ป้อนข้อมูลผู้ใช้ที่ไม่น่าเชื่อถือเป็นช่องโหว่ XSS แม้ว่า<div>
จะไม่ได้เพิ่มใน DOM:
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)">')
อย่างไรก็ตามการโจมตีครั้งนี้เป็นไปไม่ได้กับ<textarea>
เพราะไม่มีองค์ประกอบ HTML <textarea>
ที่ได้รับอนุญาตของเนื้อหา ดังนั้นแท็ก HTML ใด ๆ ที่ยังคงอยู่ในสตริง 'เข้ารหัส' จะถูกเข้ารหัสโดยอัตโนมัติโดยเบราว์เซอร์
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)">'))
คำเตือน : การทำเช่นนี้ใช้ jQuery ของ
.html()
และ.val()
วิธีการแทนการใช้.innerHTML
และ.value
ยังเป็นที่ไม่ปลอดภัย * บางรุ่น jQuery, แม้ในขณะที่ใช้textarea
เพราะนี่คือรุ่นเก่าของ jQuery จะจงใจและชัดเจนประเมินสคริปต์.html()
ที่อยู่ในสตริงที่ผ่านมา ดังนั้นรหัสเช่นนี้แสดงการแจ้งเตือนใน jQuery 1.8:
//<!-- 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>
* ขอขอบคุณEru Penkmanสำหรับการตรวจจับช่องโหว่นี้
decodedString = textArea.value;
textArea.remove();
return decodedString;
if ('remove' in Element.prototype) textArea.remove();
$("<div />").html(string).text()
จะใช้งานจาวาสคริปต์ในสตริงที่มีให้ซึ่งฉันสงสัยว่าเป็นสิ่งที่ทำให้เกิดปัญหาของคุณ คำตอบที่ยอมรับควรได้รับการอัปเดตเป็นคำตอบนี้
เช่นเดียวกับ Mike Samuel กล่าวว่าอย่าใช้ jQuery.html (). text () เพื่อถอดรหัสเอนทิตี html เนื่องจากไม่ปลอดภัย
ให้ใช้เทมเพลตเท็มเพลตเช่นMustache.jsหรือdecodeEntitiesจากความคิดเห็นของ @ VyvIT แทน
ไลบรารียูทิลิตี้เข็มขัดUnderscore.jsมาพร้อมกับescape
และunescape
วิธีการ แต่ไม่ปลอดภัยสำหรับการป้อนข้อมูลของผู้ใช้:
unescape
ในเอกสารตอนนี้ btw
_.unescape("'")
ผลลัพธ์ในเพียง "& # 39;" แทนคำพูดเดียว มีบางสิ่งที่ฉันขาดหายไปหรือขีดเส้นใต้ไม่หลบหนีไปยังรหัสเอนทิตี HTML ดังที่แสดงใน: w3schools.com/tags/ref_entities.asp
escape
และunescape
วิธีการ ... จะไม่ปลอดภัยสำหรับการป้อนข้อมูลผู้ใช้" คุณหมายถึงอะไร? ฟังดูไร้สาระสำหรับฉัน แต่บางทีฉันอาจขาดอะไรไปหน่อยคุณช่วยอธิบายได้ไหม?
_.unescape("<img src=fake onerror=alert('boo!')>")
(ใน Chrome / FF / IE) แต่มันไม่ได้แสดงการแจ้งเตือนใด ๆ พยายามในคอนโซลรวมทั้งวางไว้ในไฟล์ JS ของฉันด้วย ผลลัพธ์เดียวกัน
ฉันคิดว่าคุณสับสนกับวิธีข้อความและ HTML ดูตัวอย่างนี้หากคุณใช้ HTML ภายในขององค์ประกอบเป็นข้อความคุณจะได้รับการถอดรหัสแท็ก HTML (ปุ่มที่สอง) แต่ถ้าคุณใช้เป็น HTML คุณจะได้รับมุมมองการจัดรูปแบบ HTML (ปุ่มแรก)
<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());" />
<input value="Write as Text" type="button" onclick="javascript:$('#resultDiv').text($('#myDiv').html());" />
<br /><br />
<div id="resultDiv">
Results here !
</div>
ปุ่มแรกเขียน:นี่คือเนื้อหาHTML
ปุ่มที่สองเขียน:นี่คือเนื้อหา <B> HTML </B>
อย่างไรก็ตามคุณสามารถเห็นปลั๊กอินที่ฉันพบในปลั๊กอิน jQuery - ถอดรหัส HTML และเข้ารหัสที่เข้ารหัสและถอดรหัสสตริง HTML
คำถามถูก จำกัด โดย 'with jQuery' แต่มันอาจช่วยให้บางคนรู้ว่ารหัส jQuery ที่ให้ไว้ในคำตอบที่ดีที่สุดที่นี่ทำสิ่งต่อไปนี้ภายใต้ ... การทำงานนี้มีหรือไม่มี jQuery:
function decodeEntities(input) {
var y = document.createElement('textarea');
y.innerHTML = input;
return y.value;
}
คุณสามารถใช้ไลบรารีheได้จากhttps://github.com/mathiasbynens/he
ตัวอย่าง:
console.log(he.decode("Jörg & Jürgen rocked to & fro "));
// Logs "Jörg & Jürgen rocked to & fro"
ฉันท้าทายผู้เขียนของห้องสมุดเกี่ยวกับคำถามที่ว่ามีเหตุผลใดที่จะใช้ห้องสมุดนี้ในรหัสของลูกค้าเพื่อสนับสนุนการ<textarea>
แฮ็คที่ให้ไว้ในคำตอบอื่น ๆที่นี่และที่อื่น ๆ เขาให้เหตุผลที่เป็นไปได้สองสามข้อ:
หากคุณกำลังใช้ node.js serverside การใช้ไลบรารี่สำหรับการเข้ารหัส / ถอดรหัส HTML จะช่วยให้คุณมีโซลูชั่นเดียวที่ทำงานทั้งฝั่งไคลเอนต์และฝั่งเซิร์ฟเวอร์
บางเบราว์เซอร์นิติบุคคลถอดรหัสอัลกอริทึมมีข้อบกพร่องหรือขาดหายไปสนับสนุนสำหรับบางอ้างอิงตัวละครชื่อ ตัวอย่างเช่น Internet Explorer จะถอดรหัสและแสดงช่องว่างแบบไม่แตกหัก (
) ได้อย่างถูกต้อง แต่รายงานว่าเป็นช่องว่างทั่วไปแทนที่จะเป็นช่องว่างแบบไม่ทำลายผ่านinnerText
คุณสมบัติขององค์ประกอบ DOM ทำให้<textarea>
แฮ็ค (แม้จะเป็นเพียงเล็กน้อย) นอกจากนี้ IE 8 และ 9 ก็ไม่สนับสนุนการอ้างอิงอักขระที่มีชื่อใหม่ที่เพิ่มใน HTML 5 ผู้เขียนของเขายังโฮสต์ทดสอบการสนับสนุนการอ้างอิงอักขระที่ชื่อที่http://mathias.html5.org/tests/html / ชื่อตัวอักษรอ้างอิง / ใน IE 8 จะรายงานข้อผิดพลาดมากกว่าหนึ่งพันข้อ
หากคุณต้องการได้รับการป้องกันจากข้อบกพร่องของเบราว์เซอร์ที่เกี่ยวข้องกับการถอดรหัสเอนทิตีและ / หรือสามารถจัดการการอ้างอิงอักขระที่มีชื่อเต็มรูปแบบได้คุณจะไม่สามารถ<textarea>
แฮ็คได้ คุณจะต้องห้องสมุดเหมือนเขา
เขาแค่ยี้รู้สึกดีที่ทำสิ่งนี้ด้วยวิธีที่ไม่สมบูรณ์
เข้ารหัส:
$("<textarea/>").html('<a>').html(); // return '<a>'
ถอดรหัส:
$("<textarea/>").html('<a>').val() // return '<a>'
ใช้
myString = myString.replace( /\&/g, '&' );
มันง่ายที่สุดที่จะทำบนฝั่งเซิร์ฟเวอร์เพราะเห็นได้ชัดว่า JavaScript ไม่มีไลบรารี่ดั้งเดิมสำหรับการจัดการเอนทิตีและฉันไม่พบสิ่งใดใกล้กับด้านบนของผลการค้นหาสำหรับเฟรมเวิร์กต่าง ๆ ที่ขยายจาวาสคริปต์
ค้นหา "เอนทิตี HTML JavaScript" และคุณอาจพบว่ามีไลบรารี่บางอันสำหรับจุดประสงค์นั้น แต่พวกมันอาจจะถูกสร้างขึ้นรอบ ๆ ตรรกะด้านบน - แทนที่เอนทิตี้ของเอนทิตี
ฉันแค่ต้องมีนิติบุคคล HTML (⇓) เป็นค่าสำหรับปุ่ม HTML รหัส HTML ดูดีตั้งแต่เริ่มต้นในเบราว์เซอร์:
<input type="button" value="Embed & Share ⇓" id="share_button" />
ตอนนี้ฉันได้เพิ่มการสลับที่ควรแสดงตัวละคร นี่คือทางออกของฉัน
$("#share_button").toggle(
function(){
$("#share").slideDown();
$(this).attr("value", "Embed & Share " + $("<div>").html("⇑").text());
}
จะแสดง⇓อีกครั้งในปุ่ม ฉันหวังว่าสิ่งนี้อาจช่วยให้ใครบางคน
"Embed & Share \u21d1"
) หรือดีกว่า แต่"Embed & Share ⇑"
ถ้าคุณสามารถให้บริการสคริปต์ของคุณใน UTF-8 (หรือ UTF-16 หรือการเข้ารหัสอื่น ๆ ที่สนับสนุนอักขระ)) การใช้องค์ประกอบ DOM เพื่อแยกเอนทิตี HTML เพียงเพื่ออบอักขระยูนิโคดลงในสตริง JavaScript เป็นวิธีที่ชาญฉลาดและสร้างสรรค์ที่จะทำให้ Rube Goldberg ภูมิใจ แต่ไม่ใช่วิธีปฏิบัติที่ดี unicode escapes เป็นภาษาที่ใช้จัดการกรณีการใช้งานนี้โดยเฉพาะ
คุณต้องสร้างฟังก์ชันที่กำหนดเองสำหรับเอนทิตี html:
function htmlEntities(str) {
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g,'>').replace(/"/g, '"');
}
สมมติว่าคุณมีสตริงด้านล่าง
เคบินดีลักซ์ของเราอบอุ่นอบอุ่นเป็นกันเอง & amp; สบาย
var str = $("p").text(); // get the text from <p> tag
$('p').html(str).text(); // Now,decode html entities in your variable i.e
str และกำหนดกลับไปที่
แท็ก
แค่นั้นแหละ.
สำหรับผู้ใช้ ExtJS หากคุณมีสตริงที่เข้ารหัสแล้วเช่นเมื่อค่าที่ส่งคืนของฟังก์ชันไลบรารีคือเนื้อหา InnerHTML ให้พิจารณาฟังก์ชัน ExtJS นี้:
Ext.util.Format.htmlDecode(innerHtmlContent)
ขยายคลาส String:
String::decode = ->
$('<textarea />').html(this).text()
และใช้เป็นวิธีการ:
"<img src='myimage.jpg'>".decode()
ลองสิ่งนี้:
var htmlEntities = "<script>alert('hello');</script>";
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 และมันจะกลับอาร์เรย์ที่มีรายละเอียดบางอย่างเกี่ยวกับสตริงที่กำหนด ..
ในบางกรณี String มีขนาดใหญ่ดังนั้นฟังก์ชันจะแยกเนื้อหาออกเป็นดัชนีหลาย ๆ
และเพื่อรับข้อมูลดัชนีทั้งหมดคุณควรไปที่ดัชนีใด ๆ จากนั้นเข้าถึงดัชนีที่เรียกว่า "wholeText"
ฉันเลือกดัชนี 0 เพราะมันจะใช้ได้ในทุกกรณี (สตริงเล็กหรือสตริงใหญ่)
นี่ยังคงเป็นปัญหาหนึ่ง: สตริงที่ใช้ Escape ไม่สามารถอ่านได้เมื่อกำหนดให้กับค่าอินพุต
var string = _.escape("<img src=fake onerror=alert('boo!')>");
$('input').val(string);
Exapmle: https://jsfiddle.net/kjpdwmqa/3/
escape
วิธี Underscore.js ยังไม่มีคำอธิบายว่าตัวอย่างโค้ดของคุณควรแก้ปัญหา OP อย่างไร
นอกจากนี้ยังมีห้องสมุดสำหรับ ..
ที่นี่https://cdnjs.com/l ไลบรารี/he
npm install he //using node.js
<script src="js/he.js"></script> //or from your javascript directory
การใช้งานมีดังนี้ ...
//to encode text
he.encode('© Ande & Nonso® Company LImited 2018');
//to decode the
he.decode('© Ande & Nonso® Company Limited 2018');
ไชโย
หากต้องการถอดรหัสเอนทิตี HTML ด้วย jQuery เพียงใช้ฟังก์ชั่นนี้:
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;
}
วิธีใช้:
javascript:
var txtEncoded = "á é í ó ú";
$('#some-id').val(html_entity_decode(txtEncoded));
HTML:
<input id="some-id" type="text" />
วิธีที่ง่ายที่สุดคือตั้งตัวเลือกคลาสให้องค์ประกอบของคุณแล้วใช้รหัสต่อไปนี้:
$(function(){
$('.classSelector').each(function(a, b){
$(b).html($(b).text());
});
});
ไม่มีอะไรจำเป็นอีกแล้ว!
ฉันมีปัญหานี้และพบวิธีแก้ปัญหาที่ชัดเจนและใช้งานได้ดี
ฉันคิดว่านั่นเป็นสิ่งที่ตรงกันข้ามกับวิธีการแก้ปัญหาที่เลือก
var decoded = $("<div/>").text(encodedStr).html();