从输入字段读取属性时 HTML 编码丢失

我正在使用JavaScript从隐藏字段中提取值并将其显示在文本框中。隐藏字段中的值已编码。

例如

<input id='hiddenId' type='hidden' value='chalk &amp; cheese' />

被拉入

<input type='text' value='chalk &amp; cheese' />

通过一些jQuery从隐藏字段获取值(此时我丢失了编码):

$('#hiddenId').attr('value')

问题是,当我从隐藏字段读取时,JavaScript似乎丢失了编码。我不希望该值为 .我希望保留文字。chalk &amp; cheesechalk & cheeseamp;

是否有 JavaScript 库或 jQuery 方法可以对字符串进行 HTML 编码?


答案 1

编辑:这个答案是很久以前发布的,该函数引入了一个XSS漏洞。它已被修改,将临时元素从 a 更改为减少 XSS 几率。但是现在,我鼓励你按照其他 anwswer 中的建议使用 DOMParser API。htmlDecodedivtextarea


我使用这些函数:

function htmlEncode(value){
  // Create a in-memory element, set its inner text (which is automatically encoded)
  // Then grab the encoded contents back out. The element never exists on the DOM.
  return $('<textarea/>').text(value).html();
}

function htmlDecode(value){
  return $('<textarea/>').html(value).text();
}

基本上,文本区域元素是在内存中创建的,但它永远不会附加到文档中。

在函数上,我设置元素,并检索编码的;在函数上,我设置元素的值并检索。htmlEncodeinnerTextinnerHTMLhtmlDecodeinnerHTMLinnerText

在此处查看运行示例。


答案 2

jQuery技巧不编码引号,在IE中它会剥离你的空格。

基于Django中的转义模板标签,我想它已经被大量使用/测试过,我制作了这个函数,它可以做需要的事情。

它可以说比任何针对空格剥离问题的解决方法更简单(并且可能更快) - 并且它对引号进行编码,例如,如果要在属性值中使用结果,这是必不可少的。

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

// I needed the opposite function today, so adding here too:
function htmlUnescape(str){
    return str
        .replace(/&quot;/g, '"')
        .replace(/&#39;/g, "'")
        .replace(/&lt;/g, '<')
        .replace(/&gt;/g, '>')
        .replace(/&amp;/g, '&');
}

更新 2013-06-17:
在搜索最快的转义时,我发现了一个方法的实现:
http://dumpsite.com/forum/index.php?topic=4.msg29#msg29
(此处也引用:替换字符串中字符的所有实例的最快方法
此处的一些性能结果:
http://jsperf.com/htmlencoderegex/25replaceAll

它为上面的内置链提供相同的结果字符串。如果有人能解释为什么它更快,我会很高兴!?replace

2015-03-04更新:
我刚刚注意到AngularJS正在使用上述方法:
https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js#L435

他们添加了一些改进 - 他们似乎正在处理一个晦涩难懂的Unicode问题,以及将所有非字母数字字符转换为实体。我的印象是,只要您为文档指定了 UTF8 字符集,后者就没有必要。

我会注意到(4年后)Django仍然没有做这些事情,所以我不确定它们有多重要:
https://github.com/django/django/blob/1.8b1/django/utils/html.py#L44

2016-04-06更新:
您可能还希望转义正斜杠。对于正确的 HTML 编码,这不是必需的,但是 OWASP 建议将其作为反 XSS 安全措施。(感谢@JNF在评论中提出这一建议)/

        .replace(/\//g, '&#x2F;');