用jQuery转义HTMLstring

有谁知道一个简单的方法来从jQuery中的string转义HTML? 我需要能够传递一个任意的string,并妥善转义,以显示在HTML页面(防止JavaScript / HTML注入攻击)。 我确信有可能扩展jQuery来做到这一点,但是目前我还不太了解这个框架。

既然你使用jQuery,你可以设置元素的text属性:

 // before: // <div class="someClass">text</div> var someHtmlString = "<script>alert('hi!');</script>"; // set a DIV's text: $("div.someClass").text(someHtmlString); // after: // <div class="someClass">&lt;script&gt;alert('hi!');&lt;/script&gt;</div> // get the text in a string: var escaped = $("<div>").text(someHtmlString).html(); // value: // &lt;script&gt;alert('hi!');&lt;/script&gt; 

还有mustache.js的解决scheme

 var entityMap = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;', '/': '&#x2F;', '`': '&#x60;', '=': '&#x3D;' }; function escapeHtml (string) { return String(string).replace(/[&<>"'`=\/]/g, function (s) { return entityMap[s]; }); } 
 $('<div/>').text('This is fun & stuff').html(); // "This is fun &amp; stuff" 

资料来源: http : //debuggable.com/posts/encode-html-entities-with-jquery : 480f4dd6-13cc-4ce9-8071-4710cbdd56cb

如果你正在逃避HTML,只有三个,我可以想到,这将是非常必要的:

 html.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); 

根据您的使用情况,您可能还需要执行" to &quot; 。如果列表变得足够大,我只需要使用一个数组:

 var escaped = html; var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]] for(var item in findReplace) escaped = escaped.replace(findReplace[item][0], findReplace[item][1]); 

encodeURIComponent()只会转义它的URL,而不是HTML。

我写了一个小小的函数来做到这一点。 它只是逃避"&<> (但通常这就是你所需要的),它稍微比以前提出的解决scheme更优雅,因为它只使用一个 .replace()来完成所有的转换( 编辑2:如果您对原始代码感兴趣,请参阅本答题的结尾部分,以减less代码的复杂性,使函数更小巧整洁。

 function escapeHtml(text) { 'use strict'; return text.replace(/[\"&<>]/g, function (a) { return { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' }[a]; }); } 

这是简单的Javascript,没有使用jQuery。

逃避/'

编辑回应mklement的评论。

上述function可以很容易地扩展到包含任何字符。 要指定更多字符进行转义,只需将它们插入到正则expression式中的字符类(即/[...]/g )中,并作为chr对象中的一个条目。 ( 编辑2:同样缩短了这个function。)

 function escapeHtml(text) { 'use strict'; return text.replace(/[\"&'\/<>]/g, function (a) { return { '"': '&quot;', '&': '&amp;', "'": '&#39;', '/': '&#47;', '<': '&lt;', '>': '&gt;' }[a]; }); } 

注意上面的使用&#39; 对于撇号(可能已经使用了符号实体 – 它是用XML定义的,但是最初没有包含在HTML规范中,因此可能不被所有的浏览器支持,参见: 关于HTML字符编码的维基百科文章 )。 我还记得阅读的地方,使用十进制实体更广泛的支持比使用hex,但我似乎无法find现在的来源,但。 (并且不存在许多不支持hex实体的浏览器。)

注意:在转义字符列表中添加/'并不是那么有用,因为它们在HTML中没有任何特殊含义,也不需要转义。

原始的escapeHtml函数

编辑2:原始函数使用variables( chr )来存储.replace()callback所需的对象。 这个variables还需要一个额外的匿名函数来确定它的范围,使函数(不必要的)变得更大一些,更复杂一些。

 var escapeHtml = (function () { 'use strict'; var chr = { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' }; return function (text) { return text.replace(/[\"&<>]/g, function (a) { return chr[a]; }); }; }()); 

我还没有testing过哪个版本更快。 如果你这样做,请随时在这里添加信息和链接。

容易使用下划线:

 _.escape(string) 

Underscore是一个实用程序库,提供了许多原生js不提供的function。 还有lodash是与下划线相同的API,但被重写为更高性能。

我意识到我参加这个派对有多迟,但我有一个非常简单的解决scheme,不需要jQuery。

 escaped = new Option(unescaped).innerHTML; 

编辑:这不能逃脱报价。 唯一需要引号的情况是内容将被内嵌粘贴到HTMLstring中的属性。 我很难想象这样做的情况是好的devise。

编辑2:如果性能至关重要,性能最高的解决scheme(约50%)仍然是一系列正则expression式的替代。 现代浏览器将检测到正则expression式不包含运算符,只包含一个string,并将其全部归并为单个操作。

这是一个清晰,清晰的JavaScript函数。 它会将诸如“一些<许多”的文本转换为“一些<许多”。

 function escapeHtmlEntities (str) { if (typeof jQuery !== 'undefined') { // Create an empty div to use as a container, // then put the raw text in and get the HTML // equivalent out. return jQuery('<div/>').text(str).html(); } // No jQuery, so use string replace. return str .replace(/&/g, '&amp;') .replace(/>/g, '&gt;') .replace(/</g, '&lt;') .replace(/"/g, '&quot;'); } 

尝试Underscore.string库,它与jQuery一起工作。

 _.str.escapeHTML('<div>Blah blah blah</div>') 

输出:

 '&lt;div&gt;Blah blah blah&lt;/div&gt;' 

在上次testing之后,我可以推荐最快且完全跨浏览器兼容的原生Java脚本 (DOM)解决scheme:

 function HTMLescape(html){ return document.createElement('div') .appendChild(document.createTextNode(html)) .parentNode .innerHTML } 

如果重复多次,可以使用一次准备好的variables来完成:

 //prepare variables var DOMtext = document.createTextNode("test"); var DOMnative = document.createElement("span"); DOMnative.appendChild(DOMtext); //main work for each case function HTMLescape(html){ DOMtext.nodeValue = html; return DOMnative.innerHTML } 

看看我最后的performance比较 ( 堆栈问题 )。

我已经增强了mustache.js示例,将escapeHTML()方法添加到string对象。

 var __entityMap = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': '&quot;', "'": '&#39;', "/": '&#x2F;' }; String.prototype.escapeHTML = function() { return String(this).replace(/[&<>"'\/]/g, function (s) { return __entityMap[s]; }); } 

这样就很容易使用"Some <text>, more Text&Text".escapeHTML()

escape()unescape()旨在对URL进行编码/解码,而不是HTML。

其实,我使用下面的代码片段来做不需要任何框架的技巧:

 var escapedHtml = html.replace(/&/g, '&amp;') .replace(/>/g, '&gt;') .replace(/</g, '&lt;') .replace(/"/g, '&quot;') .replace(/'/g, '&apos;'); 

如果你有underscore.js,使用_.escape (比上面提到的jQuery方法更有效):

 _.escape('Curly, Larry & Moe'); // returns: Curly, Larry &amp; Moe 

如果你正在使用正则expression式,那么tghw的例子中有一个错误。

 <!-- WON'T WORK - item[0] is an index, not an item --> var escaped = html; var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g,"&gt;"], [/"/g, "&quot;"]] for(var item in findReplace) { escaped = escaped.replace(item[0], item[1]); } <!-- WORKS - findReplace[item[]] correctly references contents --> var escaped = html; var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]] for(var item in findReplace) { escaped = escaped.replace(findReplace[item[0]], findReplace[item[1]]); } 

这是一个很好的安全例子

 function escapeHtml(str) { if (typeof(str) == "string"){ try{ var newStr = ""; var nextCode = 0; for (var i = 0;i < str.length;i++){ nextCode = str.charCodeAt(i); if (nextCode > 0 && nextCode < 128){ newStr += "&#"+nextCode+";"; } else{ newStr += "?"; } } return newStr; } catch(err){ } } else{ return str; } } 
 (function(undefined){ var charsToReplace = { '&': '&amp;', '<': '&lt;', '>': '&gt;' }; var replaceReg = new RegExp("[" + Object.keys(charsToReplace).join("") + "]", "g"); var replaceFn = function(tag){ return charsToReplace[tag] || tag; }; var replaceRegF = function(replaceMap) { return (new RegExp("[" + Object.keys(charsToReplace).concat(Object.keys(replaceMap)).join("") + "]", "gi")); }; var replaceFnF = function(replaceMap) { return function(tag){ return replaceMap[tag] || charsToReplace[tag] || tag; }; }; String.prototype.htmlEscape = function(replaceMap) { if (replaceMap === undefined) return this.replace(replaceReg, replaceFn); return this.replace(replaceRegF(replaceMap), replaceFnF(replaceMap)); }; })(); 

没有全局variables,一些内存优化。 用法:

 "some<tag>and&symbol©".htmlEscape({'©': '&copy;'}) 

结果是:

 "some&lt;tag&gt;and&amp;symbol&copy;" 

你可以轻松地用香草js来做。

只需添加一个文本节点的文件。 它将被浏览器转义。

 var escaped = document.createTextNode("<HTML TO/ESCAPE/>") document.getElementById("[PARENT_NODE]").appendChild(escaped) 
 function htmlEscape(str) { var stringval=""; $.each(str, function (i, element) { alert(element); stringval += element .replace(/&/g, '&amp;') .replace(/"/g, '&quot;') .replace(/'/g, '&#39;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;') .replace(' ', '-') .replace('?', '-') .replace(':', '-') .replace('|', '-') .replace('.', '-'); }); alert(stringval); return String(stringval); } 

2个简单的方法,需要没有JQUERY …

您可以像这样编码string中的所有字符

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

或者只是瞄准主要的人物担心& ,换行符, <>"'像:

 function encode(r){ return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"}) } var myString='Encode HTML entities!\n"Safe" escape <script></'+'script> & other tags!'; test.value=encode(myString); testing.innerHTML=encode(myString); /************* * \x26 is &ampersand (it has to be first), * \x0A is newline, *************/ 
 <p><b>What JavaScript Generated:</b></p> <textarea id=test rows="3" cols="55"></textarea> <p><b>What It Renders Too In HTML:</b></p> <div id="testing">www.WHAK.com</div> 
 function htmlDecode(t){ if (t) return $('<div />').html(t).text(); } 

奇迹般有效

这个答案提供了jQuery和普通的JS方法,但这是最短的,而不使用DOM:

 unescape(escape("It's > 20% less complicated this way.")) 

转义string: It%27s%20%3E%2020%25%20less%20complicated%20this%20way.

如果逃脱的空间打扰你,请尝试:

 unescape(escape("It's > 20% less complicated this way.").replace(/%20/g, " ")) 

逃脱的string: It%27s %3E 20%25 less complicated this way.

不幸的是, 在JavaScript 1.5版本中 , escape()函数已经被弃用了 。 encodeURI()encodeURIComponent()是可选项,但是它们忽略了' ,所以最后一行代码会变成这样:

 decodeURI(encodeURI("It's > 20% less complicated this way.").replace(/%20/g, " ").replace("'", '%27')) 

所有主stream的浏览器仍然支持短代码,并给予旧网站的数量,我怀疑这将很快会改变。

普通的JavaScript转义示例:

 function escapeHtml(text) { var div = document.createElement('div'); div.innerText = text; return div.innerHTML; } escapeHtml("<script>alert('hi!');</script>") // "&lt;script&gt;alert('hi!');&lt;/script&gt;" 

如果要将这些信息保存在数据库中 ,那么使用客户端脚本转义HTML是错误的,这应该在服务器中完成。 否则,它很容易绕过你的XSS保护。

为了明确我的观点,下面是使用其中一个答案的例子:

比方说,你正在使用函数escapeHtml从您的博客中的评论转义Html,然后将其张贴到您的服务器。

 var entityMap = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': '&quot;', "'": '&#39;', "/": '&#x2F;' }; function escapeHtml(string) { return String(string).replace(/[&<>"'\/]/g, function (s) { return entityMap[s]; }); } 

用户可以:

  • 编辑POST请求参数并用javascript代码replace注释。
  • 使用浏览器控制台覆盖escapeHtml函数。

如果用户将此片段粘贴到控制台中,则会绕过XSSvalidation:

 function escapeHtml(string){ return string } 

所有的解决scheme都是无用的,如果你不防止再次逃脱,例如大多数解决scheme将继续逃避& &amp;

 escapeHtml = function (s) { return s ? s.replace( /[&<>'"]/g, function (c, offset, str) { if (c === "&") { var substr = str.substring(offset, offset + 6); if (/&(amp|lt|gt|apos|quot);/.test(substr)) { // already escaped, do not re-escape return c; } } return "&" + { "&": "amp", "<": "lt", ">": "gt", "'": "apos", '"': "quot" }[c] + ";"; } ) : ""; };