从input字段读取属性时,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 来自隐藏领域的chalk &amp; cheese ,JavaScript似乎失去了编码。 为了逃避"' ,我希望编码保持。

有一个JavaScript库或jQuery的方法,将HTML编码的string?

我使用这些function:

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

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

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

检查一个正在运行的例子。

jQuery技巧不会对引号进行编码,在IE中,它将会删除你的空格。

基于Django中的转义模板标签,我猜测已经被大量使用/testing过了,我做了这个function来完成需要的function。

它可以说比任何解决空白问题的解决方法都简单(也可能更快),并且它会对引号进行编码,例如,如果要使用属性值中的结果,这些引号是很重要的。

 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:
在寻找最快的转义时,我发现了这个replaceAll方法的实现:
http://dumpsite.com/forum/index.php?topic=4.msg29#msg29
(在这里也引用: 最快的方法来replacestring中的所有字符的实例 )
一些性能结果在这里:
http://jsperf.com/htmlencoderegex/25

它给上面的内置replace链提供了相同的结果string。 如果有人能解释为什么它更快,我会非常高兴!

更新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编码,这不是必需的,但OWASPbuild议将其作为反XSS安全措施。 (感谢@JNF在评论中提出这个build议)

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

这是一个非jQuery版本,比jQuery .html()版本和.replace()版本都快很多。 这保留了所有的空白,但像jQuery版本,不处理引号。

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

速度: 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 ) ) ); 

HTML:

 <input id="hidden" type="hidden" value="chalk &amp; cheese" /> <input id="text" value="" /> <div id="same"></div> 

我知道这是一个旧的,但我想发布一个接受的答案的变种,将在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" 

好答案。 请注意,如果在jQuery 1.4.2中,要编码的值是undefined或为null ,那么您可能会遇到以下错误:

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 ''; } } 

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

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

Prototype内置了String类 。 所以,如果你正在使用/计划来使用Prototype,它可以做如下的事情:

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

FWIW,编码不会丢失。 编码由页面加载期间的标记parsing器(浏览器)使用。 一旦源代码被读取和parsing,浏览器将DOM加载到内存中,编码就被parsing为代表的内容。 所以当你的JS被执行来读取内存中的任何东西时,它得到的字符就是编码所代表的内容。

我可能在这里严格地操作语义,但是我想让你理解编码的目的。 “失落”这个词使得它听起来像是不应该的东西。

更快没有JQuery。 您可以编码string中的每个字符:

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

或者只是瞄准主要人物担心(&,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, *************/ 
 <textarea id=test rows="9" cols="55"></textarea> <div id="testing">www.WHAK.com</div> 

这是一个简单的JavaScript解决scheme。 它用一个方法“HTMLEncode”来扩展String对象,该方法可以用在一个没有参数的对象上,或者带有一个参数。

 String.prototype.HTMLEncode = function(str) { var result = ""; var str = (arguments.length===1) ? str : this; for(var i=0; i<str.length; i++) { var chrcode = str.charCodeAt(i); result+=(chrcode>128) ? "&#"+chrcode+";" : str.substr(i,1) } return result; } // TEST console.log("stetaewteaw æø".HTMLEncode()); console.log("stetaewteaw æø".HTMLEncode("æåøåæå")) 

我已经做了一个“JavaScript的HTMLEncode方法”的要点 。

我有一个类似的问题,并解决它使用函数encodeURIComponent从JavaScript( 文档 )

例如,在你的情况下,如果你使用:

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

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

你会得到chalk%20%26%20cheese 。 即使空间保持。

在我的情况下,我不得不编码一个反斜杠,这个代码完美的作品

 encodeURIComponent('name/surname') 

我得到了name%2Fsurname

你不应该逃脱/编码的价值,以便他们从一个input字段穿梭到另一个。

 <form> <input id="button" type="button" value="Click me"> <input type="hidden" id="hiddenId" name="hiddenId" value="I like cheese"> <input type="text" id="output" name="output"> </form> <script> $(document).ready(function(e) { $('#button').click(function(e) { $('#output').val($('#hiddenId').val()); }); }); </script> 

JS不会插入原始HTML或任何东西; 它只是告诉DOM设置value属性(或属性;不知道)。 无论哪种方式,DOM处理任何编码问题。 除非你像使用document.writeeval那样做一些奇怪的事情,否则HTML编码将是有效透明的。

如果你正在谈论生成一个新的文本框来保存结果…它仍然很容易。 只需将HTML的静态部分传递给jQuery,然后在返回给您的对象上设置其余的属性/属性。

 $box = $('<input type="text" name="whatever">').val($('#hiddenId').val()); 

基于angular色的清理 …(es6模块语法)

 // ref: https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js const SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; const NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; const decodeElem = document.createElement('pre'); /** * Decodes html encoded text, so that the actual string may * be used. * @param value * @returns {string} decoded text */ export function decode(value) { if (!value) return ''; decodeElem.innerHTML = value.replace(/</g, '&lt;'); return decodeElem.textContent; } /** * Encodes all potentially dangerous characters, so that the * resulting string can be safely inserted into attribute or * element text. * @param value * @returns {string} encoded text */ export function encode(value) { if (value === null || value === undefined) return ''; return String(value). replace(/&/g, '&amp;'). replace(SURROGATE_PAIR_REGEXP, value => { var hi = value.charCodeAt(0); var low = value.charCodeAt(1); return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';'; }). replace(NON_ALPHANUMERIC_REGEXP, value => { return '&#' + value.charCodeAt(0) + ';'; }). replace(/</g, '&lt;'). replace(/>/g, '&gt;'); } export default {encode,decode}; 

afaik在JavaScript中没有任何直接的HTML编码/解码方法。

然而,你可以做的是使用JS来创build一个任意的元素,设置它的内部文本,然后使用innerHTML来读取它。

说,与jQuery这应该工作:

 var helper = $('chalk & cheese').hide().appendTo('body'); var htmled = helper.html(); helper.remove(); 

或者沿着这些线路

如果你想使用jQuery。 我find了这个:

http://www.jquerysdk.com/api/jQuery.htmlspecialchars

(由jQuery SDK提供的jquery.string插件的一部分)

我相信Prototype的问题在于,它扩展了JavaScript中的基础对象,并与您可能使用的任何jQuery不兼容。 当然,如果你已经在使用Prototype而不是jQuery,那不会是一个问题。

编辑:也有这个,这是jQuery的原型的string实用程序的端口:

http://stilldesigning.com/dotstring/

 var htmlEnDeCode = (function() { var charToEntityRegex, entityToCharRegex, charToEntity, entityToChar; function resetCharacterEntities() { charToEntity = {}; entityToChar = {}; // add the default set addCharacterEntities({ '&amp;' : '&', '&gt;' : '>', '&lt;' : '<', '&quot;' : '"', '&#39;' : "'" }); } function addCharacterEntities(newEntities) { var charKeys = [], entityKeys = [], key, echar; for (key in newEntities) { echar = newEntities[key]; entityToChar[key] = echar; charToEntity[echar] = key; charKeys.push(echar); entityKeys.push(key); } charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g'); entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g'); } function htmlEncode(value){ var htmlEncodeReplaceFn = function(match, capture) { return charToEntity[capture]; }; return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn); } function htmlDecode(value) { var htmlDecodeReplaceFn = function(match, capture) { return (capture in entityToChar) ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10)); }; return (!value) ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn); } resetCharacterEntities(); return { htmlEncode: htmlEncode, htmlDecode: htmlDecode }; })(); 

这是来自ExtJS源代码。

 <script> String.prototype.htmlEncode = function () { return String(this) .replace(/&/g, '&amp;') .replace(/"/g, '&quot;') .replace(/'/g, '&#39;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;'); } var aString = '<script>alert("I hack your site")</script>'; console.log(aString.htmlEncode()); </script> 

将会输出: &lt;script&gt;alert(&quot;I hack your site&quot;)&lt;/script&gt;

一旦定义,.htmlEncode()将被所有string访问。

HtmlEncodes给定的值

  var htmlEncodeContainer = $('<div />'); function htmlEncode(value) { if (value) { return htmlEncodeContainer.text(value).html(); } else { return ''; } } 

我在Domain \ Userstring中遇到了一些反斜杠问题。

我把这个加到了Anentropic的答案中

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

我在这里find了: 如何在JavaScript中转义反斜杠?

Interesting Posts