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

IT技术 javascript jquery html escaping html-escape-characters
2021-01-27 19:57:16

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

例如,

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

被拉进

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

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

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

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

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

6个回答

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


我使用这些功能:

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();
}

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

htmlEncode我设置innerText元素函数上,并检索编码的innerHTML; htmlDecode函数上,我设置了innerHTML元素值并innerText检索了 。

在此处检查运行示例

取决于浏览器,在 Firefox 上它包括空格、新行......在 IE 上它会删除所有内容。
2021-03-18 19:57:16
这适用于大多数情况,但 htmlDecode 的这种实现将消除任何额外的空白。因此,对于“输入”的某些值,输入 != htmlDecode(htmlEncode(input))。在某些情况下,这对我们来说是一个问题。例如,如果 input = "<p>\t Hi \n There </p>",往返编码/解码将产生 "<p> Hi There </p>"。大多数时候这是可以的,但有时不是。:)
2021-04-03 19:57:16

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 年 6 月 17 日更新:在寻找最快的转义过程中,我发现了一种replaceAll方法的实现
http
: //dumpsite.com/forum/index.php?topic=4.msg29# msg29(此处也引用:最快替换字符串中字符的所有实例的方法
这里的一些性能结果:http :
//jsperf.com/htmlencoderegex/25

它为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 年 4 月 6 日更新:
您可能还希望转义正斜杠/这不是正确的 HTML 编码所必需的,但是OWASP 建议将作为反 XSS 安全措施。(感谢@JNF 在评论中提出这一点)

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

这是一个非 jQuery 版本,它比 jQuery.html()版本和jQuery版本都快得多.replace()这会保留所有空格,但与 jQuery 版本一样,不处理引号。

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};

速度: http : //jsperf.com/htmlencoderegex/17

速度测试

演示: js小提琴

输出:

输出

脚本:

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};

function htmlDecode( html ) {
    var a = document.createElement( 'a' ); a.innerHTML = html;
    return a.textContent;
};

document.getElementById( 'text' ).value = htmlEncode( document.getElementById( 'hidden' ).value );

//sanity check
var html = '<div>   &amp; hello</div>';
document.getElementById( 'same' ).textContent = 
      'html === htmlDecode( htmlEncode( html ) ): ' 
    + ( html === htmlDecode( htmlEncode( html ) ) );

HTML:

<input id="hidden" type="hidden" value="chalk    &amp; cheese" />
<input id="text" value="" />
<div id="same"></div>
这就引出了一个问题:为什么它不是 JS 中的全局函数?!
2021-04-01 19:57:16

我知道这是一个旧的,但我想发布一个可接受的答案的变体,它可以在 IE 中工作而无需删除行:

function multiLineHtmlEncode(value) {
    var lines = value.split(/\r\n|\r|\n/);
    for (var i = 0; i < lines.length; i++) {
        lines[i] = htmlEncode(lines[i]);
    }
    return lines.join('\r\n');
}

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

下划线提供_.escape()_.unescape()执行此操作的方法。

> _.unescape( "chalk &amp; cheese" );
  "chalk & cheese"

> _.escape( "chalk & cheese" );
  "chalk &amp; cheese"