【问题标题】:How do I escape some html in javascript?如何在javascript中转义一些html?
【发布时间】:2011-07-12 05:06:00
【问题描述】:

给定文字

<b>This is some text</b>

我想把它写到我的页面上,这样它就会像这样显示:

&lt;b&gt;This is some text&lt;/b&gt;

不是这样的

这是一段文字

使用 escape("&lt;b&gt;This is some text&lt;/b&gt;") 在 Firefox 中给了我这个可爱的宝石

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

不完全是我所追求的。有什么想法吗?

【问题讨论】:

标签: javascript html-encode


【解决方案1】:

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

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

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

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 所指出的,此策略将适用于更多场景。

【讨论】:

  • Stephan,这是我见过的最优雅的解决方案——非常感谢您的回答! [赞成]。
  • 伙计们,如果您想要一个完整的解决方案,请移至:github.com/janl/mustache.js/blob/master/mustache.js#L55 它包括所有字符!感谢@Error 指出导致我采用该方法的文章
  • 第二个非常适合没有DOM的NodeJS;但是,我会将其扩展为不包含许多其他常见字符。它还通过编码所有不在要跳过的字符的正则表达式列表中的内容,与 HTML 规范的任何新的特殊添加实现最佳兼容。
  • 您还应该转义撇号 ('),因为它可以用来代替 HTML 中的引号来包装属性值。您可以将其替换为&amp;apos;
【解决方案2】:

我使用以下函数来转义每个带有 nnn; 符号的字符,除了 az AZ 0-9空间

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('&lt;b&gt;This is some text&lt;/b&gt;')

返回

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

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

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

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

【讨论】:

    【解决方案3】:

    这应该适合你: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;
    }
    

    安全警告

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

     var userWebsite = '" onmouseover="alert(\'gotcha\')" "';
     var profileLink = '<a href="' + escapeHtml(userWebsite) + '">Bob</a>';
     var div = document.getElemenetById('target');
     div.innerHtml = profileLink;
     // <a href="" onmouseover="alert('gotcha')" "">Bob</a>
    

    感谢buffer 指出这个案例。从this blog post 中提取的片段。

    【讨论】:

    • 哇,很棒的解决方案,人们应该注意到这个并投票更多!
    • 这是一个很好的解决方案,尽管它确实依赖于 DOM。如果您在浏览器之外使用 JavaScript,则需要以下其他解决方案之一。
    • 它不会转义引号,您可能会错误地认为将内容作为 HTML 插入是安全的。示例:benv.ca/2012/10/2/you-are-probably-misusing-DOM-text-methods
    • limc,请使用 安全 解决方案进行更新。我暂时不赞成它,因为它可怕的人可能正在实施这一点——当我看到你更新了你的答案时,我会取消反对票,然后投票赞成。谢谢!
    【解决方案4】:

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

    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>

    【讨论】:

      【解决方案5】:

      我最终这样做了:

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

      【讨论】:

      • 这与 kapa/Headshota 在您一年多之前发布的答案相同,-1 用于复制他们的答案。 (添加缩进应该是一种编辑,而不是自己承担业力。)
      • 您还应该转义撇号 ('),因为它可以用来代替 HTML 中的引号。您可以将其替换为&amp;apos;
      【解决方案6】:

      传统转义

      如果您使用的是 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>");
      

      【讨论】:

      • @cHao 是的。它很受欢迎,因为它很严格。你知道你会得到什么。
      【解决方案7】:

      试试这个htmlentities for javascript

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

      【讨论】:

      • 适用于 PHP,但问题的标签表明 JavaScript 是所需的解决方案语言。
      【解决方案8】:

      这是一个用它们的 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;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-21
        • 2015-05-16
        • 2010-11-08
        • 2011-08-06
        • 2011-12-27
        • 2011-04-11
        相关资源
        最近更新 更多