如何使用jQuery解码字符串中的HTML实体?

评论

过早选择技术(jQuery)会引发有关安全问题的答案。最好关闭它作为stackoverflow.com/questions/1912501/…的副本。

#1 楼


安全说明:使用此答案(下面以其原始形式保留)可能会在您的应用程序中引入XSS漏洞。您不应该使用此答案。阅读lucascaro的答案以获取对该答案中漏洞的解释,然后改用该答案或Mark Amery的答案中的方法。

实际上,请尝试



 var encodedStr = "This is fun & stuff";
var decoded = $("<div/>").html(encodedStr).text();
console.log(decoded); 

 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div/> 




评论


不要使用不受信任的输入执行此操作。即使该节点未连接到DOM,许多浏览器也会加载图像并引发相关事件。尝试运行$(“
”)。html('')。在Firefox或Safari中,它会触发警报。

–迈克·塞缪尔(Mike Samuel)
2011年3月16日20:37



@Mike,那么您推荐什么呢?如果您不知道要替换的内容,那么对.replace()的回答就不好了...

– ekkis
11年5月29日在1:35

@ekkis,在尝试对实体进行解码之前,需要剥离标签。 str.replace(/ <\ /?\ w(?:[^“'>] |” [^“] *” |'[^'] *')*> / g,“”)或类似的东西。

–迈克·塞缪尔(Mike Samuel)
2011年5月29日下午5:07

我对类似问题的回答是一个更好的实现(我认为),它从输入中剥离了大多数HTML标记(由Mike提供)。它也没有jQuery的开销,因此非常适合其他环境。

– Robert K
2012年3月7日21:41

@MichaelStum,您在此处所做的编辑使Mike Samuel的评论和下一个投票最高的答案都无效,并且这样做并没有真正修复所有jQuery版本的XSS漏洞(如下面的答案所述)。在此答案中添加安全警告是合理的(我将这样做);使此页面上的其他讨论变得荒谬而又无法真正解决安全漏洞绝对不是!

–马克·阿默里(Mark Amery)
16-12-28 16:08



#2 楼

没有任何jQuery:




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

console.log(decodeEntities('1 &amp; 2')); // '1 & 2' 





与已接受的答案相似,但是可以安全地用于不受信任的用户输入。


类似方法中的安全问题

正如Mike Samuel所指出的那样,即使没有将<div>从未添加到DOM中,使用<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>的攻击是不可能的,因为没有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(),使用jQuery的.val().innerHTML方法而不是使用.valuetextarea进行此操作也不安全*。这是因为较旧版本的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();返回decodedString;

–维尔纳
16-2-26在7:05

或仅当javascript版本实际上支持remove()时:if(Element.prototype中的“ remove”)textArea.remove();

–维尔纳
16-2-26在7:34

@Werner函数退出后,将不再有任何变量持有对该函数的引用,因此它将由垃圾收集器自动删除。

–user2428118
17年1月12日在14:15

我将它与.NET结合使用,只需单击一下按钮即可实现代码隐藏,由于某种原因,可接受的答案导致了回发。这个答案没有,所以这对我来说是最好的答案。谢谢!

– Snailer
17年7月14日在9:53

@Snailer $(“
”)。html(string).text()将执行提供的字符串中的所有JavaScript,我怀疑这是引起您问题的原因。接受的答案应更新为此。

– jbowman
18年1月8日在22:34

#3 楼

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

相反,请使用模板渲染器(如Mustache.js或@VyvIT的注释中的encodeEntities) 。

Underscore.js实用程序带库带有escapeunescape方法,但是它们对于用户输入而言并不安全:


_.unescape(string)

评论


这实际上值得更多的赞扬!绝对是我的首选解决方案。到目前为止,他们已经将unescape包含在文档中。

–致命吉他
13年5月17日在13:01

_.unescape("'") results in just "'" instead of a single-quote. Is there something I'm missing or does underscore not escape to HTML entity codes as shown on: w3schools.com/tags/ref_entities.asp

– Jason Axelson
Dec 2 '13 at 19:31

github上的错误已关闭,显示为“无法修复”;这意味着该解决方案将无法正常工作。

–伊戈尔·楚宾(Igor Chubin)
13年12月29日在11:03



您说Underscore的“转义和unescape方法...对于用户输入而言并不安全”。这是什么意思听起来对我来说是胡说八道,但也许我缺少了一些东西-您能澄清一下吗?

–马克·阿默里(Mark Amery)
15年7月10日在20:03

@VyvIT Tried _.unescape("<img src=fake onerror=alert('boo!')>") (in Chrome / FF/ IE). But it did not show up any alert. Tried it in console as well as put it in my JS file too. Same result.

– Vivek Athalye
Mar 5 '17 at 13:58

#4 楼

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


第一个按钮写道:这是HTML内容。

第二个按钮写道:这是 HTML 的内容。

顺便说一句,您可以看到我在jQuery插件中找到的插件-HTML解码和编码,可以对HTML字符串进行编码和解码。

#5 楼

这个问题受到“使用jQuery”的限制,但它可能会帮助一些人知道,此处最佳答案中给出的jQuery代码在下面执行了以下操作……无论是否使用jQuery,它都可以使用:

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


#6 楼

您可以使用he库,该库可从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编码/解码的库将为您提供一个在客户端和服务器端均可使用的解决方案。 br />
某些浏览器的实体解码算法存在错误或缺少对某些命名字符引用的支持。例如,Internet Explorer将正确地解码和渲染不间断空格(&nbsp;),但通过DOM元素的innerText属性将它们报告为普通空间而不是不间断空格,从而破坏了<textarea> hack(尽管仅是次要的方式)。此外,IE 8和9根本不支持HTML 5中添加的任何新的命名字符引用。他的作者还在http://mathias.html5.org/tests/html上托管了对命名字符引用支持的测试。 / named-character-references /。在IE 8中,它会报告超过一千个错误。

如果您希望避免与实体解码相关的浏览器错误和/或能够处理所有命名字符引用,则可以无法摆脱<textarea>黑客;您将需要一个像他这样的图书馆。

评论


+1 jQuery并不是万能的解决方案。使用正确的工具完成工作。

–玛蒂亚斯·拜恩斯(Mathias Bynens)
2014年5月11日19:56

这些是解码HTML实体的最佳方法。所有其他答案(关于此问题和类似问题)都使用innerHTML(创建新的HTML元素,处理HTML代码,然后获取该元素的innerHTML,如果您不太谨慎,请参阅XSS攻击,否则可能会受到XSS攻击),或者建议使用都不完整的Underscore.js unescape或Lodash unescape方法(仅适用于少数HTML实体)。 he库是最完整,最安全的选择!

–ands
19-10-24在20:17

#7 楼

编码:



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

 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea/> 




解码:



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

 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea/> 




评论


已经有一个有效的答案,并且几乎与此相同。我们不需要重复的答案

– marka软件
2014-09-21 21:48



这是有效的答案。汤姆的答案使用DIV元素,这使该答案容易受到XSS的攻击。

–弗朗西斯科·霍奇(Francisco Hodge)
16 Mar 23 '16 at 19:39

这是清晰的最佳答案。

–丹·伦道夫
17-2-28在23:28

您确定它有效吗?我的意思是可能是我的浏览器,但是在文本区域上发生的事情有点奇怪

–RuslanLópez
12月2日20:30

#8 楼

使用

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


最简单的方法是在服务器端执行此操作,因为显然JavaScript没有用于处理实体的本机库,在搜索结果的顶部附近也找不到任何库适用于扩展JavaScript的各种框架。

搜索“ JavaScript HTML实体”,您可能会为此目的找到一些库,但它们可能全部基于上述逻辑构建-逐个实体替换。

#9 楼

试试这个:




 var htmlEntities = "&lt;script&gt;alert('hello');&lt;/script&gt;";
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的一些详细信息。.

在某些情况下,String正在大,因此该函数会将内容分为多个索引。.

并获取所有索引数据,您应该转到任何索引,然后访问名为“ wholeText”的索引。

我选择了索引0,因为它可以在所有情况下使用(小字符串或大字符串)。

评论


尽管此代码段可能是解决方案,但包括说明确实有助于提高帖子的质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。

–约翰
19年3月26日在11:45

添加了解释...谢谢:)

– Fawaz Al Romy
19 Mar 26 '19 at 12:23

#10 楼

我只需要一个HTML实体字符(⇓)作为HTML按钮的值即可。 HTML代码从浏览器开始就看起来不错:

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


现在,我添加了一个切换器,该切换器也应显示字符。这是我的解决方案

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


这再次在按钮中显示⇓。希望对您有所帮助。

评论


更简单的方法是使用Unicode转义序列(即“嵌入并共享\ u21d1”),或者如果可以在UTF-8(或UTF-16,或支持⇑字符的任何其他编码)。使用DOM元素解析HTML实体只是将任意的unicode字符烘焙到JavaScript字符串中是一种狡猾且富有创造力的方法,这会让Rube Goldberg感到骄傲,但这不是一个好习惯。 unicode转义使用专门用于处理此用例的语言。

–马克·阿默里(Mark Amery)
2014年5月11日19:53



#11 楼

您必须为html实体创建自定义函数:

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


评论


我不知道,它帮助了我+1 l-)

– Szymon Toda
14年6月13日在6:53

可能因为它只处理某些实体而被否决。

–詹森
17年1月11日在1:04

最初的问题是如何解码实体-这与期望的相反。它将极其有限的字符集编码为实体。正如不赞成投票的工具提示所言,“此答案没有用”。令我惊讶的是,四年之后,它的净得分仍然很高。

– Stephen P
17年1月11日在1:40

#12 楼

Suppose you have below String.

Our Deluxe cabins are warm, cozy & comfortable

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


str and assign back to
tag.

that's it.

#13 楼

对于ExtJS用户,如果您已经有了编码的字符串,例如,当库函数的返回值是innerHTML内容时,请考虑以下ExtJS函数:

Ext.util.Format.htmlDecode(innerHtmlContent)


评论


这仅适用于5个HTML实体。您可以在文档和源代码中看到这一点。

–ands
19-10-24在18:27

#14 楼

扩展String类:

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


并用作方法:

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


#15 楼

这里仍然是一个问题:
将转义字符串分配给输入值时,它看起来不可读

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


示例:https://jsfiddle.net/kjpdwmqa/ 3 /

评论


这不是问题的答案。 OP要求解码(转义)HTML实体,但是在此答案中,您使用的是Underscore.js的转义方法。也没有解释您的代码示例应如何解决OP的问题。

–ands
19-10-24在18:42

#16 楼

或者,还有一个库。.​​

这里,https://cdnjs.com/libraries/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('&copy; Ande &amp; Nonso&reg; Company Limited 2018');


欢呼。

评论


已经有一个完整的有关he库的答案,并提供了简单的代码示例和很好的解释,说明您何时以及何时使用he库。

–ands
19-10-24在18:39

#17 楼

要使用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" />


#18 楼

最简单的方法是为您的元素设置一个类选择器,然后使用以下代码:

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


不再需要了!

我有这个问题,找到了明确的解决方案,效果很好。

评论


这不是对OP问题的答案。 OP要求在STRING中对HTML实体进行解码,这不仅不能解决OP的问题,而且还应将HTML元素中转义的HTML实体替换为不宜使用的HTML实体,不应这样做。

–ands
19-10-24在18:50

#19 楼

我认为这与选择的解决方案完全相反。

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