Câu trả lời:
Lưu ý bảo mật: sử dụng câu trả lời này (được giữ nguyên ở dạng ban đầu bên dưới) có thể đưa lỗ hổng XSS vào ứng dụng của bạn. Bạn không nên sử dụng câu trả lời này. Đọc câu trả lời của lucascaro để biết giải thích về các lỗ hổng trong câu trả lời này và sử dụng cách tiếp cận từ câu trả lời đó hoặc câu trả lời của Mark Amery .
Thật ra, hãy thử
var decoded = $("<div/>").html(encodedStr).text();
$("<div/>").html('<img src="http://www.google.com/images/logos/ps_logo2.png" onload=alert(1337)>')
. Trong Firefox hoặc Safari, nó kích hoạt cảnh báo.
str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/g, "")
hoặc một cái gì đó tương tự.
Không có bất kỳ jQuery nào:
function decodeEntities(encodedString) {
var textArea = document.createElement('textarea');
textArea.innerHTML = encodedString;
return textArea.value;
}
console.log(decodeEntities('1 & 2')); // '1 & 2'
Điều này hoạt động tương tự như câu trả lời được chấp nhận , nhưng an toàn để sử dụng với đầu vào của người dùng không tin cậy.
Như Mike Samuel đã lưu ý , thực hiện việc này <div>
thay vì <textarea>
đầu vào của người dùng không đáng tin cậy là một lỗ hổng XSS, ngay cả khi <div>
không bao giờ được thêm vào 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)">')
Tuy nhiên, cuộc tấn công này là không thể đối với a <textarea>
vì không có yếu tố HTML nào được cho phép nội dung của a <textarea>
. Do đó, mọi thẻ HTML vẫn có trong chuỗi 'được mã hóa' sẽ được trình duyệt tự động mã hóa bằng thực thể.
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)">'))
Cảnh báo : Thực hiện việc này bằng cách sử dụng jQuery
.html()
và.val()
các phương thức thay vì sử dụng.innerHTML
và.value
cũng không an toàn * đối với một số phiên bản của jQuery, ngay cả khi sử dụng atextarea
. Điều này là do các phiên bản cũ hơn của jQuery sẽ đánh giá một cách có chủ ý và rõ ràng các tập lệnh có trong chuỗi được truyền tới.html()
. Do đó mã như thế này hiển thị cảnh báo trong 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>
* Cảm ơn Eru Penkman vì đã nắm bắt được lỗ hổng này.
decodedString = textArea.value;
textArea.remove();
return decodedString;
if ('remove' in Element.prototype) textArea.remove();
$("<div />").html(string).text()
sẽ thực thi bất kỳ javascript nào trong chuỗi được cung cấp , mà tôi nghi ngờ là nguyên nhân gây ra vấn đề của bạn. Câu trả lời được chấp nhận nên được cập nhật cho câu hỏi này.
Giống như Mike Samuel đã nói, đừng sử dụng jQuery.html (). Text () để giải mã các thực thể html vì nó không an toàn.
Thay vào đó, hãy sử dụng trình kết xuất mẫu như Mustache.js hoặc decodeEntities từ nhận xét của @ VyvIT.
Thư viện vành đai tiện ích Underscore.js đi kèm escape
và unescape
các phương thức, nhưng chúng không an toàn cho đầu vào của người dùng:
unescape
trong các tài liệu bây giờ, btw.
_.unescape("'")
kết quả chỉ trong "& # 39;" thay vì một trích dẫn Có thứ gì đó tôi thiếu hoặc không gạch dưới không thoát khỏi mã thực thể HTML như được hiển thị trên: w3schools.com/tags/ref_entities.asp
escape
và unescape
phương thức ... của Underscore không an toàn cho đầu vào của người dùng" . Bạn có ý nghĩa gì bởi điều này? Nghe có vẻ vô nghĩa với tôi, nhưng có lẽ tôi đang thiếu một cái gì đó - bạn có thể làm rõ không?
_.unescape("<img src=fake onerror=alert('boo!')>")
(trong Chrome / FF / IE). Nhưng nó đã không hiển thị bất kỳ cảnh báo. Đã thử nó trong giao diện điều khiển cũng như đặt nó trong tệp JS của tôi. Cùng một kết quả.
Tôi nghĩ bạn đang nhầm lẫn giữa các phương thức văn bản và HTML. Nhìn vào ví dụ này, nếu bạn sử dụng HTML bên trong của một thành phần làm văn bản, bạn sẽ nhận được các thẻ HTML được giải mã (nút thứ hai). Nhưng nếu bạn sử dụng chúng dưới dạng HTML, bạn sẽ có chế độ xem được định dạng HTML (nút đầu tiên).
<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>
Nút đầu tiên ghi: đây là một nội dung HTML .
Nút thứ hai ghi: đây là nội dung <B> HTML </ B>.
Nhân tiện, bạn có thể thấy một trình cắm mà tôi tìm thấy trong plugin jQuery - giải mã HTML và mã hóa mã hóa và giải mã chuỗi HTML.
Câu hỏi bị giới hạn bởi 'với jQuery' nhưng nó có thể giúp một số người biết rằng mã jQuery được đưa ra trong câu trả lời hay nhất ở đây thực hiện như sau bên dưới ... điều này hoạt động có hoặc không có jQuery:
function decodeEntities(input) {
var y = document.createElement('textarea');
y.innerHTML = input;
return y.value;
}
Bạn có thể sử dụng thư viện anh ấy , có sẵn từ https://github.com/mathiasbynens/he
Thí dụ:
console.log(he.decode("Jörg & Jürgen rocked to & fro "));
// Logs "Jörg & Jürgen rocked to & fro"
Tôi đã thách thức tác giả của thư viện về câu hỏi liệu có lý do nào để sử dụng thư viện này trong mã máy khách để ủng hộ vụ <textarea>
hack được cung cấp trong các câu trả lời khác ở đây và ở nơi khác không. Ông cung cấp một vài lời biện minh có thể:
Nếu bạn đang sử dụng máy chủ node.js, sử dụng thư viện để mã hóa / giải mã HTML cung cấp cho bạn một giải pháp duy nhất hoạt động cả máy khách và máy chủ.
Các thuật toán giải mã thực thể của một số trình duyệt có lỗi hoặc thiếu hỗ trợ cho một số tham chiếu ký tự được đặt tên . Ví dụ: Internet Explorer sẽ giải mã và kết xuất không gian không phá vỡ (
) một cách chính xác nhưng báo cáo chúng là không gian thông thường thay vì không phá vỡ thông qua thuộc innerText
tính của phần tử DOM , phá vỡ <textarea>
hack (dù chỉ là một cách nhỏ). Ngoài ra, IE 8 và 9 đơn giản là không hỗ trợ bất kỳ tham chiếu ký tự có tên mới nào được thêm vào HTML 5. Tác giả của anh ta cũng tổ chức một thử nghiệm hỗ trợ tham chiếu ký tự có tên tại http://mathias.html5.org/tests/html / tên-ký tự-tài liệu tham khảo / . Trong IE 8, nó báo cáo hơn một nghìn lỗi.
Nếu bạn muốn được cách ly khỏi các lỗi trình duyệt liên quan đến giải mã thực thể và / hoặc có thể xử lý toàn bộ các tham chiếu ký tự được đặt tên, bạn không thể thoát khỏi vụ <textarea>
hack; bạn sẽ cần một thư viện như ông .
Anh ta chỉ cảm thấy như làm mọi thứ theo cách này là ít hack hơn.
mã hóa:
$("<textarea/>").html('<a>').html(); // return '<a>'
giải mã:
$("<textarea/>").html('<a>').val() // return '<a>'
Sử dụng
myString = myString.replace( /\&/g, '&' );
Dễ dàng nhất để làm điều đó ở phía máy chủ vì rõ ràng JavaScript không có thư viện riêng để xử lý các thực thể, tôi cũng không tìm thấy bất kỳ kết quả tìm kiếm nào ở gần đầu của các khung công tác mở rộng JavaScript.
Tìm kiếm "các thực thể HTML JavaScript" và bạn có thể tìm thấy một vài thư viện cho mục đích đó, nhưng tất cả chúng có thể được xây dựng xung quanh logic trên - thay thế, thực thể theo thực thể.
Tôi chỉ cần có một charater thực thể HTML () làm giá trị cho nút HTML. Mã HTML có vẻ tốt ngay từ đầu trong trình duyệt:
<input type="button" value="Embed & Share ⇓" id="share_button" />
Bây giờ tôi đã thêm một nút chuyển đổi cũng sẽ hiển thị bảng xếp hạng. Đây là giải pháp của tôi
$("#share_button").toggle(
function(){
$("#share").slideDown();
$(this).attr("value", "Embed & Share " + $("<div>").html("⇑").text());
}
Điều này sẽ hiển thị ⇓ một lần nữa trong nút. Tôi hy vọng điều này có thể giúp một ai đó.
"Embed & Share \u21d1"
) hoặc tốt hơn là chỉ "Embed & Share ⇑"
khi bạn có thể phục vụ tập lệnh của mình trong UTF-8 (hoặc UTF-16 hoặc bất kỳ mã hóa nào khác hỗ trợ ký tự). Sử dụng một phần tử DOM để phân tích một thực thể HTML chỉ để nướng một ký tự unicode tùy ý vào một chuỗi JavaScript là một cách tiếp cận sáng tạo và khôn ngoan sẽ khiến Rube Goldberg tự hào, nhưng không phải là cách thực hành tốt; thoát unicode là trong ngôn ngữ đặc biệt để xử lý trường hợp sử dụng này.
Bạn phải tạo chức năng tùy chỉnh cho các thực thể html:
function htmlEntities(str) {
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g,'>').replace(/"/g, '"');
}
Giả sử bạn có chuỗi bên dưới.
Cabin Deluxe của chúng tôi ấm áp, ấm cúng & amp; Thoải mái
var str = $("p").text(); // get the text from <p> tag
$('p').html(str).text(); // Now,decode html entities in your variable i.e
str và gán lại cho
nhãn.
đó là nó.
Đối với người dùng ExtJS, nếu bạn đã có chuỗi được mã hóa, ví dụ: khi giá trị được trả về của hàm thư viện là nội dung bên trongHTML, hãy xem xét hàm ExtJS này:
Ext.util.Format.htmlDecode(innerHtmlContent)
Mở rộng một lớp String:
String::decode = ->
$('<textarea />').html(this).text()
và sử dụng như phương pháp:
"<img src='myimage.jpg'>".decode()
Thử cái này :
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>
phân tích là một Hàm trong thư viện Jquery và nó sẽ trả về một mảng bao gồm một số chi tiết về Chuỗi đã cho ..
trong một số trường hợp, Chuỗi đang lớn, do đó, hàm sẽ phân tách nội dung thành nhiều chỉ mục ..
và để có được tất cả các dữ liệu chỉ mục, bạn nên truy cập vào bất kỳ chỉ mục nào, sau đó truy cập vào chỉ mục có tên là "WholeText".
Tôi đã chọn chỉ số 0 vì nó sẽ hoạt động trong mọi trường hợp (Chuỗi nhỏ hoặc chuỗi lớn).
Đây vẫn là một vấn đề: Chuỗi thoát không thể đọc được khi được gán cho giá trị đầu vào
var string = _.escape("<img src=fake onerror=alert('boo!')>");
$('input').val(string);
Exapmle: https://jsfiddle.net/kjpdwmqa/3/
escape
phương thức Underscore.js. Ngoài ra, không có lời giải thích làm thế nào mẫu mã của bạn sẽ giải quyết vấn đề của OP.
Ngoài ra, cũng có một thư viện cho nó ..
tại đây, https://cdnjs.com/lologists/he
npm install he //using node.js
<script src="js/he.js"></script> //or from your javascript directory
Cách sử dụng như sau ...
//to encode text
he.encode('© Ande & Nonso® Company LImited 2018');
//to decode the
he.decode('© Ande & Nonso® Company Limited 2018');
chúc mừng
Để giải mã các thực thể HTML bằng jQuery, chỉ cần sử dụng chức năng này:
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;
}
Cách sử dụng:
Javascript:
var txtEncoded = "á é í ó ú";
$('#some-id').val(html_entity_decode(txtEncoded));
HTML:
<input id="some-id" type="text" />
Cách dễ nhất là đặt bộ chọn lớp cho các thành phần của bạn và sau đó sử dụng mã sau:
$(function(){
$('.classSelector').each(function(a, b){
$(b).html($(b).text());
});
});
Không còn gì cần thiết nữa!
Tôi đã có vấn đề này và tìm thấy giải pháp rõ ràng này và nó hoạt động tốt.