如何使用jQuery解码HTML实体?

如何使用jQuery解码string中的HTML实体?

安全注意事项:使用这个答案(保留在下面的原始格式)可能会在您的应用程序中引入XSS漏洞 。 你不应该使用这个答案。 阅读lucascaro的答案 ,解释这个答案中的漏洞,并用这个答案或Mark Amery的答案来代替。

其实,试试吧

var decoded = $("<div/>").html(encodedStr).text(); 

没有任何jQuery:

 function decodeEntities(encodedString) { var textArea = document.createElement('textarea'); textArea.innerHTML = encodedString; return textArea.value; } console.log(decodeEntities('1 &amp; 2')); // '1 & 2' 

这与接受的答案类似,但可以安全地使用不可信的用户input。


类似方法中的安全问题

正如Mike Samuel指出的那样 ,即使<div> DOM <div>永远不会被添加到DOM,但是使用不可信用户input的<div>而不是<textarea> <div>来执行此操作是XSS漏洞:

 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>来说是不可能的,因为没有允许<textarea>内容的HTML元素。 因此,仍然存在于“编码”string中的任何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()的string中包含的脚本 。 因此,像这样的代码在jQuery 1.8中显示了一个警报:

 // Shows alert $('<textarea>').html('<script>alert(1337)</script>').text() 

*感谢Eru Penkman抓住这个漏洞。

就像Mike Samuel所说的,不要使用jQuery.html()。text()来解码html实体,因为它是不安全的。

相反,使用模板渲染器,如Mustache.js或来自@ VyvIT评论的decodeEntities。

Underscore.js公用程序库带有escapeunescape方法,但是它们对用户input不安全:

_.escape(串)

_.unescape(串)

我认为你混淆了文本和HTML方法。 看看这个例子,如果你使用元素的内部HTML作为文本,你会得到解码的HTML标签(第二个button)。 但是,如果您将它们用作HTML,则将获得HTML格式的视图(第一个button)。

 <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());" /> &nbsp;&nbsp; <input value="Write as Text" type="button" onclick="javascript:$('#resultDiv').text($('#myDiv').html());" /> <br /><br /> <div id="resultDiv"> Results here ! </div> 

第一个button写道:这里是一个HTML内容。

第二个button写入:这是一个<B> HTML </ B>内容。

顺便说一下,你可以看到我在jQuery插件中find的插件 – HTML解码和编码 ,它编码和解码HTMLstring。

这个问题受到'使用jQuery'的限制,但它可能会帮助一些人知道,在这里最好的答案给出的jQuery代码做下面的下面…这与无jQuery的工作:

 function decodeEntities(input) { var y = document.createElement('textarea'); y.innerHTML = input; return y.value; } 

你可以使用他的图书馆,从https://github.com/mathiasbynens/he

例:

 console.log(he.decode("J&#246;rg &amp J&#xFC;rgen rocked to &amp; fro ")); // Logs "Jörg & Jürgen rocked to & fro" 

我向图书馆的作者提出了这样一个问题:在客户端代码中是否有任何理由使用这个库来支持在这里和别处的其他答案中提供的<textarea> hack。 他提供了一些可能的理由:

  • 如果使用node.js服务器端,使用HTML编码/解码库可以为客户端和服务器端提供单一的解决scheme。

  • 一些浏览器的实体解码algorithm有缺陷或缺less对某些命名字符引用的支持。 例如,Internet Explorer将正确地解码和呈现不间断空格( &nbsp; ),但通过DOM元素的innerText属性将它们报告为普通空间而不是非中断空间,破坏<textarea> hack(虽然只在一个小的办法)。 另外,IE 8和9 不支持在HTML 5中添加的任何新的命名字符引用。 的作者还在http://mathias.html5.org/tests/html上主持了对命名字符引用支持的testing/ named-character-references / 。 在IE 8中,它报告了一千多个错误。

    如果你想避免与实体解码相关的浏览器错误和/或能够处理全部的命名字符引用,那么你<textarea> hack; 你需要一个像这样的图书馆。

  • 他只是觉得这样做是不太冒险的。

编码:

 $("<textarea/>").html('<a>').html(); // return '&lt;a&gt' 

解码:

 $("<textarea/>").html('&lt;a&gt').val() // return '<a>' 

使用

 myString = myString.replace( /\&amp;/g, '&' ); 

在服务器端最容易做到这一点,因为显然JavaScript没有用于处理实体的本地库,也没有find任何扩展JavaScript的各种框架的search结果的顶部附近。

search“JavaScript HTML实体”,你可能会为此find一些库,但它们可能都是build立在上述逻辑的基础上的 – 按实体replace。

你必须为html实体定制函数:

 function htmlEntities(str) { return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g,'&gt;').replace(/"/g, '&quot;'); } 

我只需要将HTML实体特征(⇓)作为HTMLbutton的值。 HTML代码从浏览器开始看起来很不错:

 <input type="button" value="Embed & Share &dArr;" id="share_button" /> 

现在我正在添加一个切换,也应该显示特性。 这是我的解决scheme

 $("#share_button").toggle( function(){ $("#share").slideDown(); $(this).attr("value", "Embed & Share " + $("<div>").html("&uArr;").text()); } 

这会在button中再次显示⇓。 我希望这可以帮助某人。

假设你有下面的String。

我们的豪华客舱温暖,舒适, 自在

 var str = $("p").text(); // get the text from <p> tag $('p').html(str).text(); // Now,decode html entities in your variable ie 

str并分配回

标签。

而已。

对于ExtJS用户,如果你已经有了编码的string,例如当一个库函数的返回值是innerHTML内容的时候,考虑这个ExtJS函数:

 Ext.util.Format.htmlDecode(innerHtmlContent) 

扩展一个String类:

 String::decode = -> $('<textarea />').html(this).text() 

并用作方法:

 "&lt;img src='myimage.jpg'&gt;".decode() 

这仍然是一个问题:转义string在分配给input值时看起来不可读

 var string = _.escape("<img src=fake onerror=alert('boo!')>"); $('input').val(string); 

Exapmle: https ://jsfiddle.net/kjpdwmqa/3/

最简单的方法是将类select器设置为元素,然后使用以下代码:

 $(function(){ $('.classSelector').each(function(a, b){ $(b).html($(b).text()); }); }); 

什么都不需要!

我有这个问题,发现这个清晰的解决scheme,它工作正常。

要使用jQuery解码HTML实体,只需使用以下函数:

 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 = "&aacute; &eacute; &iacute; &oacute; &uacute;"; $('#some-id').val(html_entity_decode(txtEncoded)); 

HTML:

 <input id="some-id" type="text" /> 

我认为这与所选解决scheme完全相反。

 var decoded = $("<div/>").text(encodedStr).html();