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


当前回答

编码:

$(“<textarea/>”).html('<a>').html(); // 返回 '&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/>

其他回答

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

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

不使用jQuery:

function decodeEntities(encodedString) { var textArea = document.createElement('textarea'); textArea.innerHTML = encodedString; 返回文本区域值; } console.log(decodeEntities('1 &amp; 2'));'1 & 2'

这与可接受的答案类似,但用于不受信任的用户输入是安全的。


类似方法中的安全问题

正如Mike Samuel所指出的,使用<div>而不是使用不受信任的用户输入的<textarea>是一个XSS漏洞,即使<div>从未添加到DOM:

函数decode (encodedString) { var div = document.createElement('div'); div.innerHTML = encodedString; 返回div.textContent; } //显示警报 decodeEntities('<img src="nonexistent_image" onerror="alert(1337)">')

但是,这种攻击对<textarea>是不可能的,因为没有允许<textarea>内容的HTML元素。因此,任何HTML标记仍然出现在'encoded'字符串中,浏览器将自动对其进行实体编码。

函数decode (encodedString) { var textArea = document.createElement(' textArea '); 文本区域。innerHTML = encodedString; 返回textArea.value; } //安全,并返回正确的答案 console.log(decodeEntities('<img src="nonexistent_image" onerror="alert(1337)">')))

警告:使用jQuery的.html()和.val()方法而不是使用. innerhtml和.value对于某些版本的jQuery来说也是不安全的,即使在使用textarea时也是如此。这是因为旧版本的jQuery会故意显式地计算传递给.html()的字符串中包含的脚本。因此,在jQuery 1.8中,这样的代码显示了一个警告:

<!-- CDATA 显示警报 $(“<textarea>”) .html(“<script>警报(1337);</script>”) .text(); //--> <script src=“https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js”></script>

*感谢Eru Penkman捕获此漏洞。

您不需要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('&awconint;&CounterClockwiseContourIntegral;&#x02233;&#8755;⪪#x02233⪫');</script>"));
// Prints: <script>alert('∳∳∳∳⪪#x02233⪫');</script>

顺便说一下,我选择使用字符⪪和⪫,因为它们很少被使用,因此通过匹配它们影响性能的几率显著降低。

或者,也有一个库。

在这里,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');

欢呼。

扩展String类:

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

And use as method:

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