我可以在JavaScript中转义HTML特殊字符吗?

我想通过JavaScript函数将文本显示为HTML。如何在JavaScript中转义HTML特殊字符?有API吗?

361671 次浏览

这里有一个几乎适用于所有浏览器的解决方案:

function escapeHtml(unsafe)
{
return unsafe
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}

如果你只支持现代浏览器(2020+),那么你可以使用新的replaceAll函数:

const escapeHtml = (unsafe) => {
return unsafe.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&#039;');
}

你可以使用jQuery的.text()函数

例如:

http://jsfiddle.net/9H6Ch/

关于.text()函数的jQuery文档:

我们需要知道这个方法 转义提供的字符串 必须这样才能渲染 正确的HTML格式。为了做到这一点,它调用 DOM方法。createtextnode ()

以前版本的jQuery文档是这样写的(重点补充道):

我们需要知道这个方法在必要时转义提供的字符串,以便在HTML中正确呈现。为此,它调用DOM方法.createTextNode(), 用HTML实体替换特殊字符(如&lt;& lt;)。

我想我找到了正确的方法……

// Create a DOM Text node:
var text_node = document.createTextNode(unescaped_text);


// Get the HTML element where you want to insert the text into:
var elem = document.getElementById('msg_span');


// Optional: clear its old contents
//elem.innerHTML = '';


// Append the text node into it:
elem.appendChild(text_node);

试试这个,使用prototype.js库:

string.escapeHTML();

试听demo

function escapeHtml(html){
var text = document.createTextNode(html);
var p = document.createElement('p');
p.appendChild(text);
return p.innerHTML;
}


// Escape while typing & print result
document.querySelector('input').addEventListener('input', e => {
console.clear();
console.log( escapeHtml(e.target.value) );
});
<input style='width:90%; padding:6px;' placeholder='&lt;b&gt;cool&lt;/b&gt;'>

找到一个更好的解决方案是很有趣的:

var escapeHTML = function(unsafe) {
return unsafe.replace(/[&<"']/g, function(m) {
switch (m) {
case '&':
return '&amp;';
case '<':
return '&lt;';
case '"':
return '&quot;';
default:
return '&#039;';
}
});
};

我没有解析>,因为它不会破坏结果中的XML/HTML代码。

以下是基准:http://jsperf.com/regexpairs 另外,我还创建了一个通用的escape函数:http://jsperf.com/regexpairs2

你可以对字符串中的每个字符进行编码:

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('How to encode\nonly html tags &<>\'" nice & fast!');


/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<textarea id=test rows="9" cols="55">&#119;&#119;&#119;&#46;&#87;&#72;&#65;&#75;&#46;&#99;&#111;&#109;</textarea>

我想出了这个解决方案。

假设我们想向元素添加一些HTML,其中包含来自用户或数据库的不安全数据。

var unsafe = 'some unsafe data like <script>alert("oops");</script> here';


var html = '';
html += '<div>';
html += '<p>' + unsafe + '</p>';
html += '</div>';


element.html(html);

对于XSS攻击是不安全的。现在加上这个: $ (document.createElement (div)) . html(不安全)。text (); < / p >

就是这样

var unsafe = 'some unsafe data like <script>alert("oops");</script> here';


var html = '';
html += '<div>';
html += '<p>' + $(document.createElement('div')).html(unsafe).text(); + '</p>';
html += '</div>';


element.html(html);

对我来说,这比使用.replace()要容易得多,而且它会删除!!所有可能的HTML标签(我希望)。

使用Lodash:

_.escape('fred, barney, & pebbles');
// => 'fred, barney, &amp; pebbles'

源代码

DOM元素通过赋值给innerText来支持将文本转换为HTML。innerText不是一个函数,但是给它赋值就好像文本被转义了一样。

document.querySelectorAll('#id')[0].innerText = 'unsafe " String >><>';

显示未编码文本最简洁有效的方法是使用textContent属性。

比使用innerHTML要好。这还没有考虑到逃逸开销。

document.body.textContent = 'a <b> c </b>';

这是目前为止我见过的最快的方法。另外,它不需要在页面上添加、删除或更改元素。

function escapeHTML(unsafeText) {
let div = document.createElement('div');
div.innerText = unsafeText;
return div.innerHTML;
}

我在构建DOM结构时遇到了这个问题。这个问题帮助我解决了这个问题。我想使用双雪佛龙作为路径分隔符,但追加一个新的文本节点直接导致转义字符代码显示,而不是字符本身:

var _div = document.createElement('div');
var _separator = document.createTextNode('&raquo;');
//_div.appendChild(_separator); /* This resulted in '&raquo;' being displayed */
_div.innerHTML = _separator.textContent; /* This was key */

如果你已经在你的应用程序中使用模块,你可以使用escape-html模块。

import escapeHtml from 'escape-html';
const unsafeString = '<script>alert("XSS");</script>';
const safeString = escapeHtml(unsafeString);

在JavaScript中删除字符串中的HTML标签:

const strippedString = htmlString.replace(/(<([^>]+)>)/gi, "");


console.log(strippedString);

照章办事

OWASP建议, [e]除字母数字字符外,[你应该]转义所有ASCII值小于256的字符,使用&#xHH;格式(或命名实体,如果可用),以防止切换出[一个]属性。

这里有一个函数可以做到这一点,并有一个用法示例:

function escapeHTML(unsafe) {
return unsafe.replace(
/[\u0000-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u00FF]/g,
c => '&#' + ('000' + c.charCodeAt(0)).slice(-4) + ';'
)
}


document.querySelector('div').innerHTML =
'<span class=' +
escapeHTML('"fakeclass" onclick="alert("test")') +
'>' +
escapeHTML('<script>alert("inspect the attributes")\u003C/script>') +
'</span>'
<div></div>

You should verify the entity ranges I have provided to validate the safety of the function yourself. You could also use this regular expression which has better readability and should cover the same character codes, but is about 10% less performant in my browser:

/(?![0-9A-Za-z])[\u0000-\u00FF]/g

只需在<pre><code class="html-escape">....</code></pre>之间编写代码。确保在代码标记中添加了类名。它将转义所有写在
中的HTML片段 <pre><code class="html-escape">....</code></pre> . < / p >

const escape = {
'"': '&quot;',
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
}
const codeWrappers = document.querySelectorAll('.html-escape')
if (codeWrappers.length > 0) {
codeWrappers.forEach(code => {
const htmlCode = code.innerHTML
const escapeString = htmlCode.replace(/"|&|<|>/g, function (matched) {
return escape[matched];
});
code.innerHTML = escapeString
})
}
<pre>
<code class="language-html html-escape">
<div class="card">
<div class="card-header-img" style="background-image: url('/assets/card-sample.png');"></div>
<div class="card-body">
<p class="card-title">Card Title</p>
<p class="card-subtitle">Srcondary text</p>
<p class="card-text">Greyhound divisively hello coldly wonderfully marginally far upon
excluding.</p>
<button class="btn">Go to </button>
<button class="btn btn-outline">Go to </button>
</div>
</div>
</code>
</pre>