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

AJM*_*AJM 728 html javascript jquery escaping html-escape-characters

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

例如,

<input id='hiddenId' type='hidden' value='chalk &amp; cheese' />
Run Code Online (Sandbox Code Playgroud)

被拉进去

<input type='text' value='chalk &amp; cheese' />
Run Code Online (Sandbox Code Playgroud)

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

$('#hiddenId').attr('value')
Run Code Online (Sandbox Code Playgroud)

问题是,当我chalk &amp; cheese从隐藏字段中读取时,JavaScript似乎失去了编码.为了逃避chalk & cheeseamp;,我想编码保留.

是否有一个JavaScript库或jQuery方法将对字符串进行HTML编码?

CMS*_*CMS 1062

我使用这些功能:

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();
}
Run Code Online (Sandbox Code Playgroud)

基本上,div元素在内存中创建,但它永远不会附加到文档中.

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

在这里查看一个运行示例.

  • 这适用于大多数场景,但htmlDecode的这种实现将消除任何额外的空白.因此对于某些"输入"值,输入!= htmlDecode(htmlEncode(input)).在某些情况下,这对我们来说是一个问题.例如,如果input ="<p>\t Hi \n那里</ p>",则往返编码/解码将产生"<p> Hi There </ p>".大多数情况下这是可以的,但有时却不是.:) (95认同)
  • 虽然两年后回答,但@Anentropic下面的反应在各方面都有所改善. (29认同)
  • 谢谢你的解决方案!我通过在文本值中替换类似%% NL %%的新行来解决消除额外空白问题,然后调用.html()来获取HTML编码值,然后用<br />替换%% NL %% s ...不是防弹但工作,我的用户不太可能输入%% NL %%. (6认同)
  • 此解决方案可能取决于页面是以html还是xhtml编写,因此我倾向于不涉及DOM的解决方案. (2认同)
  • 似乎不适用于编码 `"`,我试过 `$('&lt;div/&gt;').text('"').html();` 但这只是给了我 `"`。 (2认同)

Ane*_*pic 553

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, '&');
}
Run Code Online (Sandbox Code Playgroud)

更新2013-06-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-04-06:
您可能还希望逃避正斜杠/.这对于正确的HTML编码不是必需的,但是OWASP建议将其作为反XSS安全措施.(感谢@JNF在评论中提出建议)

        .replace(/\//g, '&#x2F;');
Run Code Online (Sandbox Code Playgroud)

  • @Ferruccio ......以及为什么不使用' 请参阅:http://stackoverflow.com/questions/2083754/why-shouldnt-apos-be-used-to-escape-single-quotes http://blogs.msdn.com/b/kirillosenkov/archive/2010/03 /19/apos-is-in-xml-in-html-use-39.aspx http://fishbowl.pastiche.org/2003/07/01/the_curse_of_apos/ (31认同)
  • 如果没有`/ g`,`.replace()`将只替换第一个匹配. (9认同)
  • 谢谢,我从未意识到`''不是有效的HTML实体. (5认同)
  • 你也可以使用`'`而不是'&#39;` (2认同)

Thi*_*iff 79

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

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};
Run Code Online (Sandbox Code Playgroud)

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

速度测试

演示: 的jsfiddle

输出:

产量

脚本:

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 ) ) );
Run Code Online (Sandbox Code Playgroud)

HTML:

<input id="hidden" type="hidden" value="chalk    &amp; cheese" />
<input id="text" value="" />
<div id="same"></div>
Run Code Online (Sandbox Code Playgroud)

  • 这引出了一个问题:为什么它不是JS中的全局函数?! (17认同)
  • 最近由@SEoF建议的非正则表达式.replace()`版本变得更快:http://jsperf.com/htmlencoderegex/22 (2认同)

boc*_*oca 32

我知道这是一个旧的,但我想发布一个接受的答案的变体,将在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();
} 
Run Code Online (Sandbox Code Playgroud)


TJ *_*oll 29

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

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

> _.escape( "chalk & cheese" );
  "chalk &amp; cheese"
Run Code Online (Sandbox Code Playgroud)


lee*_*ers 12

好答案.请注意,如果要编码的值是undefinednull使用jQuery 1.4.2,则可能会出现以下错误:

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 '';
    }
}
Run Code Online (Sandbox Code Playgroud)

  • `jQuery('<div />').text(value ||'').html()` (8认同)
  • @roufamatic - 漂亮的单行.但是使用`if`检查非空的`value`可以保存必须动态创建DIV并获取它的值.如果`htmlEncode`被大量调用并且`value`可能是空的,那么这可以更高效. (3认同)
  • 好点子.好吧,总有`?:`:-) (2认同)

小智 11

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

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


JAA*_*lde 6

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

我可能在这里严格操作语义,但我希望你理解编码的目的."迷失"这个词听起来似乎有些东西不像它应该的那样工作.


Dav*_*own 6

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

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

或者只是针对主角担心(&,inebreaks,<,>,"和'),如:

function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}

test.value=encode('Encode HTML entities!\n\n"Safe" escape <script id=\'\'> & useful in <pre> tags!');

testing.innerHTML=test.value;

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
Run Code Online (Sandbox Code Playgroud)
<textarea id=test rows="9" cols="55"></textarea>

<div id="testing">www.WHAK.com</div>
Run Code Online (Sandbox Code Playgroud)


Sin*_*our 5

Prototype内置了String类.因此,如果您正在使用/计划使用Prototype,它会执行以下操作:

'<div class="article">This is an article</div>'.escapeHTML();
// -> "&lt;div class="article"&gt;This is an article&lt;/div&gt;"
Run Code Online (Sandbox Code Playgroud)

  • 在查看Prototype的解决方案之后,这就是它所做的......`.replace(/&/ g,'&amp;').replace(/ </ g,'&lt;').replace(/>/g,' &gt;');`足够简单. (9认同)
  • 不应该用引号做点什么吗?这不好 (5认同)