从input字段读取属性时,HTML编码丢失
我正在使用JavaScript从隐藏字段中提取值并将其显示在文本框中。 隐藏字段中的值被编码。
例如,
<input id='hiddenId' type='hidden' value='chalk & cheese' />
被拉进去
<input type='text' value='chalk & cheese' />
通过一些jQuery从隐藏字段获取值(在这一点上,我失去了编码):
$('#hiddenId').attr('value')
问题是,当我读chalk & cheese
来自隐藏领域的chalk & 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, '&') .replace(/"/g, '"') .replace(/'/g, ''') .replace(/</g, '<') .replace(/>/g, '>'); } // I needed the opposite function today, so adding here too: function htmlUnescape(str){ return str .replace(/"/g, '"') .replace(/'/g, "'") .replace(/</g, '<') .replace(/>/g, '>') .replace(/&/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, '/');
这是一个非jQuery版本,比jQuery .html()
版本和.replace()
版本都快很多。 这保留了所有的空白,但像jQuery版本,不处理引号。
function htmlEncode( html ) { return document.createElement( 'a' ).appendChild( document.createTextNode( html ) ).parentNode.innerHTML; };
速度: http : //jsperf.com/htmlencoderegex/17
演示:
输出:
脚本:
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> & hello</div>'; document.getElementById( 'same' ).textContent = 'html === htmlDecode( htmlEncode( html ) ): ' + ( html === htmlDecode( htmlEncode( html ) ) );
HTML:
<input id="hidden" type="hidden" value="chalk & 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 & cheese" ); "chalk & cheese" > _.escape( "chalk & cheese" ); "chalk & 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(); // -> "<div class="article">This is an article</div>"
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 &ersand (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.write
或eval
那样做一些奇怪的事情,否则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, '<'); 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, '&'). 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, '<'). replace(/>/g, '>'); } 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实用程序的端口:
var htmlEnDeCode = (function() { var charToEntityRegex, entityToCharRegex, charToEntity, entityToChar; function resetCharacterEntities() { charToEntity = {}; entityToChar = {}; // add the default set addCharacterEntities({ '&' : '&', '>' : '>', '<' : '<', '"' : '"', ''' : "'" }); } 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, '&') .replace(/"/g, '"') .replace(/'/g, ''') .replace(/</g, '<') .replace(/>/g, '>'); } var aString = '<script>alert("I hack your site")</script>'; console.log(aString.htmlEncode()); </script>
将会输出: <script>alert("I hack your site")</script>
一旦定义,.htmlEncode()将被所有string访问。
HtmlEncodes给定的值
var htmlEncodeContainer = $('<div />'); function htmlEncode(value) { if (value) { return htmlEncodeContainer.text(value).html(); } else { return ''; } }
我在Domain \ Userstring中遇到了一些反斜杠问题。
我把这个加到了Anentropic的答案中
.replace(/\\/g, '\')
我在这里find了: 如何在JavaScript中转义反斜杠?