如何使用 jQuery 解码字符串中的 HTML 实体?
如何使用 jQuery 解码 HTML 实体?
安全说明:使用此答案(保留在下面的原始形式)可能会在您的应用程序中引入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/>
没有任何 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>
而不是使用 a来执行此<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)">')
然而,这种攻击是不可能针对 a 的,<textarea>
因为没有允许 a 的内容的 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捕获此漏洞。
就像 Mike Samuel 所说的那样,不要使用 jQuery.html().text() 来解码 html 实体,因为它是不安全的。
相反,使用来自 @VyvIT 评论的Mustache.js或decodeEntities等模板渲染器。
Underscore.js实用程序带库带有escape
和unescape
方法,但它们对于用户输入并不安全:
我认为您混淆了文本和 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 decode and encode,它对HTML字符串进行编码和解码。
该问题受到“使用 jQuery”的限制,但它可能有助于某些人知道此处最佳答案中给出的 jQuery 代码在下面执行以下操作……这在使用或不使用 jQuery 的情况下都有效:
function decodeEntities(input) {
var y = document.createElement('textarea');
y.innerHTML = input;
return y.value;
}