显然,这比我想象的要难找到。而且它是如此简单...
是否有等效于Javascript中内置的PHP htmlspecialchars的函数?我知道自己很容易实现,但是使用内置函数(如果可用)会更好。
对于那些不熟悉PHP的人,htmlspecialchars会将类似的内容<htmltag/>
转换为<htmltag/>
我知道这一点escape()
,encodeURI()
因此不能这样工作。
显然,这比我想象的要难找到。而且它是如此简单...
是否有等效于Javascript中内置的PHP htmlspecialchars的函数?我知道自己很容易实现,但是使用内置函数(如果可用)会更好。
对于那些不熟悉PHP的人,htmlspecialchars会将类似的内容<htmltag/>
转换为<htmltag/>
我知道这一点escape()
,encodeURI()
因此不能这样工作。
Answers:
解决方案代码存在问题-它只会转义每个特殊字符的第一次出现。例如:
escapeHtml('Kip\'s <b>evil</b> "test" code\'s here');
Actual: Kip's <b>evil</b> "test" code's here
Expected: Kip's <b>evil</b> "test" code's here
这是正常工作的代码:
function escapeHtml(text) {
return text
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
以下代码将产生与上面相同的结果,但是它的性能更好,尤其是在大块文本上(感谢jbo5112)。
function escapeHtml(text) {
var map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
}
那就是HTML编码。没有本机的javascript函数可以执行此操作,但是您可以使用google并完成一些很好的操作。
例如http://sanzon.wordpress.com/2008/05/01/neat-little-html-encoding-trick-in-javascript/
编辑:
这是我测试过:
var div = document.createElement('div');
var text = document.createTextNode('<htmltag/>');
div.appendChild(text);
console.log(div.innerHTML);
输出: <htmltag/>
encodeURIComponent
执行操作,而根本不执行OP的要求。那你可以编辑吗?我似乎无法撤消-1。
div
元素和文本节点。用文本`<img src = bogus onerror = alert(1337)>`创建文本节点只会创建一个文本节点,而不是img
元素。
值得一读:http : //bigdingus.com/2007/12/29/html-escaping-in-javascript/
escapeHTML: (function() {
var MAP = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
var repl = function(c) { return MAP[c]; };
return function(s) {
return s.replace(/[&<>'"]/g, repl);
};
})()
注意:仅运行一次。不要在已经编码字符串如运行它&
变成&amp;
使用jQuery可以像这样:
var escapedValue = $('<div/>').text(value).html();
来自相关问题使用jQuery转义HTML字符串
如注释中所述,在此实现中,双引号和单引号保持原样。这意味着如果需要将element属性设置为原始html字符串,则不应使用此解决方案。
<!-- Caps rage begin -->
该答案的得分为负,因为它甚至没有回答“ HtmlSpecialChars等效”问题。 <!-- Caps rage end -->
它不会逃脱引用耶稣基督和其他神灵。天哪,你是jquery人。
这是一个转义HTML的函数:
function escapeHtml(str)
{
var map =
{
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return str.replace(/[&<>"']/g, function(m) {return map[m];});
}
并解码:
function decodeHtml(str)
{
var map =
{
'&': '&',
'<': '<',
'>': '>',
'"': '"',
''': "'"
};
return str.replace(/&|<|>|"|'/g, function(m) {return map[m];});
}
Underscore.js为此提供了一个功能:
_.escape(string)
转义用于插入HTML的字符串,并替换&,<,>,“和”字符。
http://underscorejs.org/#escape
它不是内置的Javascript函数,但是如果您已经在使用Underscore,则它比写自己的函数(如果要转换的字符串不太大)更好。
另一个建议是完全放弃所有字符映射,而将所有不需要的字符转换为它们各自的数字字符引用,例如:
function escapeHtml(raw) {
return raw.replace(/[&<>"']/g, function onReplace(match) {
return '&#' + match.charCodeAt(0) + ';';
});
}
请注意,指定的RegEx仅处理OP想要转义的特定字符,但是根据要使用转义的HTML的上下文,这些字符可能不足。Ryan Grove的文章对HTML进行转义的内容不仅仅包括&,<,>和“,这是该主题的不错阅读。而且,根据您的上下文,可能非常需要以下RegEx以避免XSS注入:
var regex = /[&<>"'` !@$%()=+{}[\]]/g
您可能不需要这样的功能。由于您的代码已经在浏览器中*,因此您可以直接访问DOM,而不必生成和编码HTML,而这些HTML必须由浏览器向后解码才能实际使用。
Use innerText
属性可以安全地将纯文本插入DOM中,并且比使用任何提供的转义功能要快得多。甚至比将静态预编码的字符串分配给还要快innerHTML
。
使用classList
到编辑类,dataset
以一套data-
属性和setAttribute
他人。
所有这些都将为您处理转义。更准确地说,因为您正在处理DOM的文本表示形式HTML,所以不需要转义,并且在其下不会进行编码**。
// use existing element
var author = 'John "Superman" Doe <john@example.com>';
var el = document.getElementById('first');
el.dataset.author = author;
el.textContent = 'Author: '+author;
// or create a new element
var a = document.createElement('a');
a.classList.add('important');
a.href = '/search?q=term+"exact"&n=50';
a.textContent = 'Search for "exact" term';
document.body.appendChild(a);
// actual HTML code
console.log(el.outerHTML);
console.log(a.outerHTML);
.important { color: red; }
<div id="first"></div>
*此答案不适用于服务器端JavaScript用户(Node.js 等)
**除非您之后将其明确转换为实际的HTML。例如,通过访问innerHTML
-这是您$('<div/>').text(value).html();
在其他答案中建议运行时发生的情况。因此,如果您的最终目标是向文档中插入一些数据,则通过这种方式您将进行两次工作。您还可以看到,在生成的HTML中,并非所有内容都进行了编码,仅对其有效所需的最小值进行了编码。它是依赖于上下文完成的,这就是为什么此jQuery方法不对引号进行编码的原因,因此不应用作通用转义符。当您将HTML构造为在属性值的位置具有不可信或包含引号的数据的字符串时,需要使用引号转义。如果使用DOM API,则完全不必担心转义。
el.textContent = str; el.innerHTML = el.innerHTML.replace(/\n/g, '<br>')
)替换它们,或将CSS white-space
属性设置为pre
或pre-wrap
我正在详细说明okw的答案。
您可以为此使用浏览器的DOM功能。
var utils = {
dummy: document.createElement('div'),
escapeHTML: function(s) {
this.dummy.textContent = s
return this.dummy.innerHTML
}
}
utils.escapeHTML('<escapeThis>&')
这返回 <escapeThis>&
它使用标准函数createElement
创建一个不可见的元素,然后使用该函数textContent
将任何字符串设置为其内容,然后innerHTML
以其HTML表示形式获取该内容。
function htmlspecialchars(str) {
if (typeof(str) == "string") {
str = str.replace(/&/g, "&"); /* must do & first */
str = str.replace(/"/g, """);
str = str.replace(/'/g, "'");
str = str.replace(/</g, "<");
str = str.replace(/>/g, ">");
}
return str;
}
希望这能因其性能而赢得比赛,最重要的是不要使用.replace('&','&')。replace('<','<')的链式逻辑...
var mapObj = {
'&':"&",
'<':"<",
'>':">",
'"':""",
'\'':"'"
};
var re = new RegExp(Object.keys(mapObj).join("|"),"gi");
function escapeHtml(str)
{
return str.replace(re, function(matched)
{
return mapObj[matched.toLowerCase()];
});
}
console.log('<script type="text/javascript">alert('Hello World');</script>');
console.log(escapeHtml('<script type="text/javascript">alert('Hello World');</script>'));
反转一:
function decodeHtml(text) {
return text
.replace(/&/g, '&')
.replace(/</ , '<')
.replace(/>/, '>')
.replace(/"/g,'"')
.replace(/'/g,"'");
}
<
,并&gr;
在一个字符串。
To write a greater than sign in HTML type &gt;
显示:,它将显示错误,>
而不是>
OWASP建议 “除字母数字字符外,[您应]使用&#xHH;
格式(或命名实体,如果可用)转义ASCII值小于256的所有字符,以防止切换出[an]属性。”
因此,下面是一个使用示例的函数:
function escapeHTML(unsafe) {
return unsafe.replace(
/[\u0000-\u002F]|[\u003A-\u0040]|[\u005B-\u00FF]/g,
c => '&#' + ('000' + c.charCodeAt(0)).substr(-4, 4) + ';'
)
}
document.querySelector('div').innerHTML =
'<span class=' +
escapeHTML('this should break it! " | / % * + , - / ; < = > ^') +
'>' +
escapeHTML('<script>alert("inspect the attributes")\u003C/script>') +
'</span>'
<div></div>
function htmlEscape(str){
return str.replace(/[&<>'"]/g,x=>'&#'+x.charCodeAt(0)+';')
}
此解决方案使用字符的数字代码,例如<
替换为<
。
尽管其性能比使用map的解决方案稍差,但它具有以下优点: