如何在 javascript 中转义某些 html?

问题描述 投票:0回答:8

鉴于文本

<b>This is some text</b>

我想将其写入我的页面,以便它显示如下:

<b>This is some text</b>

而不是这样

这是一些文字

使用

escape("<b>This is some text</b>")
给了我在 firefox 中这个可爱的宝石

%3Cb%3EThis%20is%20some%20text%3C/b%3E

不完全是我想要的。有什么想法吗?

javascript html-encode
8个回答
61
投票

这应该适合您:http://blog.nickburwell.com/2011/02/escape-html-tags-in-javascript.html

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

安全警告

此函数仅转义 HTML,不会转义单引号和双引号,如果在错误的上下文中使用,仍然可能导致 XSS。例如:

 // >> ⚠️ WARNING: VULNERABILITY SHOWCASE WITH SINGLE AND DOUBLE QUOTE
 var userWebsite = '" onmouseover="alert(\'gotcha\')" "';
 var profileLink = '<a href="' + escapeHtml(userWebsite) + '">Bob</a>';
 // << DON'T FOLLOW THIS EXAMPLE
 
 var div = document.getElemenetById('target');
 div.innerHtml = profileLink;
 // <a href="" onmouseover="alert('gotcha')" "">Bob</a>

感谢buffer指出这个案例。摘自此博文的片段。


43
投票

我喜欢 @limc 对于 HTML DOM 文档可用的情况的回答。

我喜欢 @Michele Bosi 和 @Paolo 对非 HTML DOM 文档环境(例如 Node.js)的回答。

@Michael Bosi 的答案可以通过消除调用替换 4 次的需要来优化,只需调用一次替换并结合巧妙的替换函数即可:

function escape(s) {
    let lookup = {
        '&': "&amp;",
        '"': "&quot;",
        '\'': "&apos;",
        '<': "&lt;",
        '>': "&gt;"
    };
    return s.replace( /[&"'<>]/g, c => lookup[c] );
}
console.log(escape("<b>This is 'some' text.</b>"));

@Paolo 的范围测试可以通过精心选择的正则表达式进行优化,并且可以通过使用替换函数来消除 for 循环:

function escape(s) {
    return s.replace(
        /[^0-9A-Za-z ]/g,
        c => "&#" + c.charCodeAt(0) + ";"
    );
}
console.log(escape("<b>This is 'some' text</b>"));

正如 @Paolo 所言,该策略将适用于更多场景。


27
投票

我最终这样做了:

function escapeHTML(s) { 
    return s.replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;');
}

7
投票

尝试这个 htmlentities for javascript

function htmlEntities(str) {
    return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}

4
投票

传统逃亡

如果您使用 XHTML,则需要使用

CDATA
部分。 您也可以在 HTML 中使用它们,但 HTML 没有那么严格。

我拆分了字符串常量,以便此代码可以在 CDATA 块内的 XHTML 上内联工作。 如果您将 JavaScript 作为单独的文件获取,那么您无需为此烦恼。 请注意,如果您正在使用带有内联JavaScript的XHTML,那么您需要将代码包含在CDATA块中,否则其中一些将不起作用。 你会遇到奇怪的、微妙的错误。

function htmlentities(text) {
    var escaped = text.replace(/\]\]>/g, ']]' + '>]]&gt;<' + '![CDATA[');
    return '<' + '![CDATA[' + escaped + ']]' + '>';
}

DOM 文本节点

转义文本的“正确”方法是使用 DOM 函数

document.createTextNode
。 这实际上并没有逃避文本;它只是告诉浏览器创建一个文本元素,该元素本质上是未解析的。 但是,您必须愿意使用 DOM 才能使此方法起作用:也就是说,您可以使用
appendChild
等方法,而不是
innerHTML
属性及类似属性。 这将用文本填充 ID 为
an-element
的元素,该文本不会被解析为 (X)HTML:

var textNode = document.createTextNode("<strong>This won't be bold.  The tags " +
    "will be visible.</strong>");
document.getElementById('an-element').appendChild(textNode);

jQuery DOM 包装器

jQuery 为

createTextNode
提供了一个方便的包装器,名为
text
。 相当方便。 这是使用 jQuery 的相同功能:

$('#an-element').text("<strong>This won't be bold.  The tags will be " +
    "visible.</strong>");

2
投票

这是一个用 html 实体替换尖括号的函数。您可能还想扩展它以包含其他角色。

function htmlEntities( html ) {
    html = html.replace( /[<>]/g, function( match ) {
        if( match === '<' ) return '&lt;';
        else return '&gt;';
    });
    return html;
}

console.log( htmlEntities( '<b>replaced</b>' ) ); // &lt;b&gt;replaced&lt;/b&gt;

2
投票

您可以对字符串中的所有字符进行编码:

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>


0
投票

我使用以下函数,使用 &#nnn; 符号转义除 a-z A-Z 0-9space

之外的每个字符
function Escape( s )
{
    var h,
        i,
        n,
        c;

    n = s.length;
    h = '';

    for( i = 0; i < n; i++ )
    {
        c = s.charCodeAt( i );
        if( ( c >= 48 && c <= 57 ) 
          ||( c >= 65 && c <= 90 ) 
          ||( c >= 97 && c <=122 )
          ||( c == 32 ) )
        {
            h += String.fromCharCode( c );
        }
        else
        {
            h += '&#' + c + ';';
        }
    }

    return h;
}

示例:

Escape('<b>This is some text</b>')

退货

&#60;b&#62;This is some text&#60;&#47;b&#62;

该功能是代码注入攻击证明,unicode证明,纯JavaScript。

这种方法比创建 DOM 文本节点的方法大约 50 倍,但该函数仍然可以在 100-150 毫秒内转义一百万 (1,000,000) 个字符的字符串。

(在 2011 年初的 MacBook Pro - Safari 9 - Mavericks 上测试)

© www.soinside.com 2019 - 2024. All rights reserved.