如何使用jQuery解码字符串中的HTML实体?
答案 0 :(得分:428)
安全提示:使用此答案(保存在下面的原始表单中)可能会在您的应用程序中引入XSS vulnerability。 您不应该使用此答案。请阅读lucascaro's answer以获取此答案中漏洞的说明,并使用该答案或Mark Amery's answer的方法。
实际上,试试
var decoded = $("<div/>").html(encodedStr).text();
答案 1 :(得分:193)
没有任何jQuery:
function decodeEntities(encodedString) {
var textArea = document.createElement('textarea');
textArea.innerHTML = encodedString;
return textArea.value;
}
console.log(decodeEntities('1 & 2')); // '1 & 2'
这与accepted answer类似,但可以安全地使用不受信任的用户输入。
作为noted by 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>
无法进行此攻击,因为没有允许<textarea>
内容的HTML元素。因此,“编码”字符串中仍然存在的任何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
。这是因为传递给.html()
的字符串中包含的旧版jQuery deliberately and explicitly evaluate scripts。因此,像这样的代码在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抓住此漏洞。
答案 2 :(得分:78)
就像Mike Samuel所说,不要使用jQuery.html()。text()解码html实体,因为它不安全。
相反,请使用@ VyvIT评论中的Mustache.js或decodeEntities等模板渲染器。
Underscore.js实用工具带库附带escape
和unescape
方法,但它们对用户输入不安全:
<强> _.escape(string) 强>
<强> _.unescape(string) 强>
答案 3 :(得分:28)
我认为你混淆了文本和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 内容。
第二个按钮写道:这里是一个&lt; B&gt; HTML&lt; / B&gt;内容。
顺便说一下,您可以看到我在 jQuery plugin - HTML decode and encode 中找到的插件,它对HTML字符串进行编码和解码。
答案 4 :(得分:26)
这个问题受到'with jQuery'的限制,但它可能有助于一些人知道在这里的最佳答案中给出的jQuery代码在下面做了以下...这有或没有jQuery:
function decodeEntities(input) {
var y = document.createElement('textarea');
y.innerHTML = input;
return y.value;
}
答案 5 :(得分:17)
您可以使用 https://github.com/mathiasbynens/he
中提供的他库示例:
console.log(he.decode("Jörg & Jürgen rocked to & fro "));
// Logs "Jörg & Jürgen rocked to & fro"
我challenged the library's author关于是否有任何理由在客户端代码中使用此库以支持other answers此处及其他地方提供的<textarea>
hack的问题。他提供了一些可能的理由:
如果您正在使用node.js服务器端,则使用用于HTML编码/解码的库可以为您提供一个适用于客户端和服务器端的单一解决方案。
某些浏览器的实体解码算法存在错误或缺少对某些named character references的支持。例如,Internet Explorer将正确解码和呈现非中断空格(
),但通过DOM元素的innerText
属性将它们报告为普通空格而不是非中断空格,从而打破{{1 hack(尽管只是一种次要的方式)。此外,IE 8和9只是don't support在HTML 5中添加的任何新命名的字符引用。他的作者还在http://mathias.html5.org/tests/html/named-character-references/主持了对命名字符引用支持的测试。在IE 8中,它报告了超过一千个错误。
如果您希望与实体解码相关的浏览器错误和/或能够处理所有命名的字符引用,您无法摆脱<textarea>
黑客攻击;你需要一个像他这样的图书馆。
他只是觉得用这种方式做事就不那么黑了。
答案 6 :(得分:17)
编码:
$("<textarea/>").html('<a>').html(); // return '<a>'
解码:
$("<textarea/>").html('<a>').val() // return '<a>'
答案 7 :(得分:4)
使用
myString = myString.replace( /\&/g, '&' );
最容易在服务器端进行,因为显然JavaScript没有用于处理实体的本机库,也没有找到任何接近扩展JavaScript的各种框架的搜索结果的顶部。
搜索“JavaScript HTML实体”,您可能会找到一些用于此目的的库,但它们可能都是围绕上述逻辑构建的 - 逐个实体替换。
答案 8 :(得分:1)
您必须为html实体制作自定义函数:
function htmlEntities(str) {
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g,'>').replace(/"/g, '"');
}
答案 9 :(得分:0)
您不需要 jQuery 来解决这个问题,因为它会产生一些开销和依赖性。
我知道这里有很多好的答案,但由于我实施了一些不同的方法,所以我想分享一下。
这段代码是一种完全安全的安全方法,因为转义处理程序取决于浏览器,而不是函数。因此,如果将来发现某些漏洞,则涵盖此解决方案。
const decodeHTMLEntities = text => {
// Create a new element or use one from cache, to save some element creation overhead
const el = decodeHTMLEntities.__cache_data_element
= decodeHTMLEntities.__cache_data_element
|| document.createElement('div');
const enc = text
// Prevent any mixup of existing pattern in text
.replace(/⪪/g, '⪪#')
// Encode entities in special format. This will prevent native element encoder to replace any amp characters
.replace(/&([a-z1-8]{2,31}|#x[0-9a-f]+|#\d+);/gi, '⪪$1⪫');
// Encode any HTML tags in the text to prevent script injection
el.textContent = enc;
// Decode entities from special format, back to their original HTML entities format
el.innerHTML = el.innerHTML
.replace(/⪪([a-z1-8]{2,31}|#x[0-9a-f]+|#\d+)⪫/gi, '&$1;')
.replace(/⪪#/g, '⪪');
// Get the decoded HTML entities
const dec = el.textContent;
// Clear the element content, in order to preserve a bit of memory (in case the text is big)
el.textContent = '';
return dec;
}
// Example
console.log(decodeHTMLEntities("<script>alert('∳∳∳∳⪪#x02233⪫');</script>"));
// Prints: <script>alert('∳∳∳∳⪪#x02233⪫');</script>
顺便说一下,我选择使用字符 ⪪
和 ⪫
,因为它们很少使用,因此通过匹配它们来影响性能的可能性要低得多。
答案 10 :(得分:0)
尝试一下:
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是因为它在所有情况下(小字符串或大字符串)都适用。
答案 11 :(得分:0)
或者,还有一个库。
在这里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('© Ande & Nonso® Company Limited 2018');
欢呼。
答案 12 :(得分:0)
这仍然是一个问题: 转换后的字符串在分配给输入值时看起来不可读
var string = _.escape("<img src=fake onerror=alert('boo!')>");
$('input').val(string);
Exapmle:https://jsfiddle.net/kjpdwmqa/3/
答案 13 :(得分:0)
扩展String类:
String::decode = ->
$('<textarea />').html(this).text()
并用作方法:
"<img src='myimage.jpg'>".decode()
答案 14 :(得分:0)
对于ExtJS用户,如果您已经有编码字符串,例如当库函数的返回值是innerHTML内容时,请考虑以下ExtJS函数:
Ext.util.Format.htmlDecode(innerHtmlContent)
答案 15 :(得分:0)
假设你有以下字符串。
我们的豪华客舱温暖,舒适,放大;舒适
var str = $("p").text(); // get the text from <p> tag
$('p').html(str).text(); // Now,decode html entities in your variable i.e
str并分配回
标签。
是的。
答案 16 :(得分:0)
我只需要一个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());
}
再次在按钮中显示⇓。我希望这可以帮助别人。
答案 17 :(得分:-2)
最简单的方法是为元素设置一个类选择器,然后使用以下代码:
$(function(){
$('.classSelector').each(function(a, b){
$(b).html($(b).text());
});
});
不再需要了!
我遇到了这个问题并找到了这个明确的解决方案,并且工作正常。
答案 18 :(得分:-3)
我认为这与所选择的解决方案完全相反。
var decoded = $("<div/>").text(encodedStr).html();
答案 19 :(得分:-3)
要使用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 = "á é í ó ú";
$('#some-id').val(html_entity_decode(txtEncoded));
<强> HTML:强>
<input id="some-id" type="text" />