ChatGPT解决这个技术问题 Extra ChatGPT

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

我正在使用 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;

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

你能显示你正在使用的Javascript吗?
添加了我如何从隐藏字段中获取价值
不要使用 innerHTML 方法(jQuery .html() 方法使用 innerHTML),因为在某些(我只测试过 Chrome)浏览器上,这不会转义引号,所以如果你要将你的值放入属性值,您最终会遇到 XSS 漏洞。
在什么情况下 chalkcheese 曾经一起使用 0_o
@d-_-b 比较两个项目时。例子。它们就像粉笔和奶酪一样不同;)

C
Chirag Soni

编辑: 这个答案是很久以前发布的,htmlDecode 函数引入了 XSS 漏洞。它已被修改,将临时元素从 div 更改为 textarea,从而减少了 XSS 机会。但是现在,我鼓励您按照 other 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

检查一个正在运行的示例 here


这适用于大多数情况,但 htmlDecode 的这种实现将消除任何额外的空白。因此对于“输入”的某些值,输入!= htmlDecode(htmlEncode(input))。在某些情况下,这对我们来说是个问题。例如,如果 input = "

\t Hi \n There

",则往返编码/解码将产生 "

Hi There

"。大多数时候这没关系,但有时不是。 :)
取决于浏览器,在 Firefox 上,它包括空格、换行符……在 IE 上,它会删除所有内容。
C
Community

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
(也在这里引用: Fastest method to replace all instances of a character in a string)
这里有一些性能结果:
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

他们添加了一些改进 - 他们似乎正在处理 obscure Unicode issue 以及将所有非字母数字字符转换为实体。我的印象是,只要您为文档指定了 UTF8 字符集,就不需要后者。

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

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

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

T
ThinkingStiff

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

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

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

https://i.stack.imgur.com/NI3c4.png

输出:

https://i.stack.imgur.com/zE07Z.png

脚本:

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 中的全局函数?!
C
Community

我知道这是一个旧的,但我想发布一个 the accepted answer 的变体,它可以在 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();
} 

T
TJ VanToll

Underscore 提供了执行此操作的 _.escape()_.unescape() 方法。

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

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

l
leepowers

好答案。请注意,如果使用 jQuery 1.4.2 编码的值为 undefinednull,您可能会收到如下错误:

jQuery("<div/>").text(value).html is not a function

或者

Uncaught TypeError: Object has no method 'html'

解决方案是修改函数以检查实际值:

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

jQuery('<div/>').text(value || '').html()
t
tdog

对于那些喜欢纯 javascript 的人,这是我成功使用的方法:

function escapeHTML (str)
{
    var div = document.createElement('div');
    var text = document.createTextNode(str);
    div.appendChild(text);
    return div.innerHTML;
}

J
JAAulde

FWIW,编码没有丢失。在页面加载期间,标记解析器(浏览器)使用编码。一旦源代码被读取和解析并且浏览器将 DOM 加载到内存中,编码就被解析为它所代表的内容。因此,当您的 JS 被执行以读取内存中的任何内容时,它获得的字符就是编码所代表的内容。

我可能在这里严格按照语义操作,但我希望您了解编码的目的。 “丢失”这个词让人听起来好像有些东西没有按应有的方式工作。


D
Dave Brown

没有 Jquery 更快。您可以对字符串中的每个字符进行编码:

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}

或者只针对主要角色担心(&,inebreaks,<,>,“和'),例如:

函数编码(r){ return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"}) } test.value=encode('编码 HTML 实体!\n\n"Safe" 转义