使用jQuery转义HTML字符串

655

有没有人知道在jQuery中从字符串中轻松转义HTML的方法?我需要能够传递任意字符串并使其正确地转义以在HTML页面中显示(防止JavaScript/HTML注入攻击)。我相信可以扩展jQuery来做到这一点,但是我目前还不了解该框架足够的知识以实现此目标。


另请参见性能测试:https://jsperf.com/jquery-html-vs-text-vs-innerhtml-vs-innertext-textconte/8 - Christophe Roussy
27个回答

1
function htmlDecode(t){
   if (t) return $('<div />').html(t).text();
}

非常好用


文本删除HTML标签,但是$('<div />').html(t).html();可以工作。 - Bass Jobsen

0
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);
}

0

用于转义HTML特殊字符(UTF-8)

function htmlEscape(str) {
  return str
      .replace(/&/g, '&amp;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#39;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/\//g, '&#x2F;')
      .replace(/=/g,  '&#x3D;')
      .replace(/`/g, '&#x60;');
}

用于反转义 HTML 特殊字符(UTF-8)

function htmlUnescape(str) {
  return str
      .replace(/&amp;/g, '&')
      .replace(/&quot;/g, '"')
      .replace(/&#39;/g, "'")
      .replace(/&lt;/g, '<')
      .replace(/&gt;/g, '>')
      .replace(/&#x2F/g, '/')
      .replace(/&#x3D;/g, '=')
      .replace(/&#x60;/g, '`');
}

0
一个经过速度优化的版本:

function escapeHtml(s) {
   let out = "";
   let p2 = 0;
   for (let p = 0; p < s.length; p++) {
      let r;
      switch (s.charCodeAt(p)) {
         case 34: r = "&quot;"; break;  // "
         case 38: r = "&amp;" ; break;  // &
         case 39: r = "&#39;" ; break;  // '
         case 60: r = '&lt;'  ; break;  // <
         case 62: r = '&gt;'  ; break;  // >
         default: continue;
      }
      if (p2 < p) {
         out += s.substring(p2, p);
      }
      out += r;
      p2 = p + 1;
   }
   if (p2 == 0) {
      return s;
   }
   if (p2 < s.length) {
      out += s.substring(p2);
   }
   return out;
}

const s = "Hello <World>!";
document.write(escapeHtml(s));
console.log(escapeHtml(s));


-2

如果你不防止重新转义,所有的解决方案都是无用的,例如,大多数解决方案会将&转义为&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] + ";";
        }
    ) : "";
};

4
这被称为双重转义,应该通过确保您的输入数据没有被转义来进行修复。如果您想要向用户文字显示 <,或者文本将在其他地方重复使用并且依赖于已经发生的转义呢? - thelem

-2

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

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

转义字符串:It%27s%20%3E%2020%25%20less%20complicated%20this%20way. 如果转义的空格让您感到不方便,请尝试:
unescape(escape("It's > 20% less complicated this way.").replace(/%20/g, " "))

转义字符串:这样做会使它变得不那么复杂,减少了20%的工作量。

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

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

所有主要的浏览器仍然支持短代码,并且考虑到旧网站的数量,我认为这种情况不会很快改变。


这是用于URL编码的。问题是关于HTML转义的,这与URL编码非常不同。 - thelem
@thelem,如果字符串嵌入在HTML中的JavaScript数组中,那么不需要转义。但我同意这是关于纯HTML转义的问题,以便可以立即显示为文本。 - Cees Timmerman

-3
如果您将此信息保存在数据库中,使用客户端脚本转义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代码。
  • 使用浏览器控制台覆盖escapeHtml函数。

如果用户将此片段粘贴到控制台中,则可以绕过XSS验证:

function escapeHtml(string){
   return string
}

我不同意。要绕过这种XSS保护,您必须使用XSS攻击(注入禁用转义的脚本),这正是您实际上要阻止的。在某些情况下,在客户端进行转义实际上更为合适,例如如果数据来自必须返回标准JSON的REST API。 - ItalyPaleAle
@Qualcuno 如果您在客户端进行此验证并将此信息发布到服务器,信任它已经过验证,则用户可以轻松编辑请求,并将脚本保存在数据库中。 - Kauê Gimenes
@Qualcuno,我包含了一些例子来更清晰地阐述我的观点。 - Kauê Gimenes
1
这个问题是关于如何转义从服务器接收到的字符串以在浏览器上显示它们。而你所说的是关于在提交到服务器之前转义字符串,这是一件不同的事情(尽管你在那里是正确的,并且它回归到旧规则永远不要盲目地接受来自客户端的任何输入)。 - ItalyPaleAle
@Qualcuno 这是Stackoverflow上一个流行的问题,我认为这是一个重要的点需要涵盖,所以我回答了。 - Kauê Gimenes
@Qualcuno,答案相当开放,这就是为什么我认为我们应该涵盖所有要点的原因。 - Kauê Gimenes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接