在HTML中,哪些字符需要转义?

375

它们和XML一样吗,也许还加上了空格符( )?

我找到了一些HTML转义字符的大列表,但我认为它们不一定需要被转义。我想知道必须被转义的是什么。


我觉得应该有一个原生函数来处理这个。我们已经有了encodeURI()来处理URL字符串的目的。我们需要同样的东西来处理HTML中用引号括起来的字符,也许是encodeHTML()或者encodeQuotes()? 在我的情况下,我需要将一个值放在alt标签中。<img alt="这里放值">。在那个位置放置HTML会破坏元素。 - 1.21 gigawatts
5个回答

493
如果您在文档中插入文本内容的位置是期望文本内容的地方1通常只需要转义与XML中相同的字符。在元素内部,这仅包括实体转义符号"ampersand" &和元素定界符号小于号和大于号 < >
& becomes &amp;
< becomes &lt;
> becomes &gt;

在属性值内部,您还必须转义使用的引号字符:

" becomes &quot;
' becomes &#39;

在某些情况下,跳过转义这些字符可能是安全的,但我建议您在所有情况下都转义这五个字符,以减少出错的机会。
如果您的文档编码不支持您使用的所有字符,例如如果您尝试在ASCII编码的文档中使用表情符号,则还需要转义这些字符。大多数文档现在都使用完全支持Unicode的UTF-8编码进行编码,因此不需要这样做。
通常情况下,您不应将空格转义为&nbsp;&nbsp;不是正常的空格,它是一个不间断空格。您可以使用这些而不是普通空格来防止在两个单词之间插入换行符,或者插入额外的空格而不会自动折叠,但这通常是一种罕见的情况。除非您有需要,否则不要这样做。

1 “期望文本内容出现的位置”是指在元素内或带引号的属性值内,应用正常解析规则。例如:<p>HERE</p><p title="HERE">...</p>。我上面所写的不适用于具有特殊解析规则或含义的内容,例如在脚本或样式标记内,或作为元素或属性名称。例如:<NOT-HERE>...</NOT-HERE><script>NOT-HERE</script><style>NOT-HERE</style><p NOT-HERE="...">...</p>

在这些上下文中,规则更加复杂,很容易引入安全漏洞。 我强烈不建议您在任何这些位置插入动态内容。 我曾经看到过一些有能力的安全意识开发人员团队因为假定已正确编码这些值,但却错过了一个边缘情况而引入漏洞。通常有更安全的替代方案,例如将动态值放入属性中,然后使用JavaScript处理它。

如果必须这样做,请阅读开放式Web应用安全项目的XSS预防规则,以帮助了解您需要记住的一些问题。


8
一些HTML属性值可能也有特殊含义(JS/CSS)。因此,这也不适用于这些情况,例如:<p onclick="NOT-HERE">...</p><p style="NOT-HERE">...</p> - geekley
1
请注意替换的顺序很重要。您必须首先替换 &。这是显而易见的,但很容易犯错。因此,您的代码应该类似于:displayTitle = title.replaceAll('&','&amp').replaceAll('<','&lt').replaceAll('>','&gt;').replaceAll("'",'&#39;').replaceAll('"','&quot;'); - tst
@tst 这是一个更新,添加了分号:displayTitle = title.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll("'", '&#39;').replaceAll('"', '&quot;'); - 1.21 gigawatts

22

14

基本上,在HTML和XML文件中,应该始终转义三个主要字符,以便它们不与其余的标记发生交互。正如您可能预期的那样,其中两个将是语法包装器,即<>,它们如下所列:

 1)  &lt; (<)
    
 2)  &gt; (>)
    
 3)  &amp; (&)

双引号(")可用作",单引号(')可用作&apos

避免在<script><style>中放置动态内容。这些规则不适用于它们。例如,如果必须在中包含JSON,则在JSON序列化后将<替换为\x3c,U+2028字符用\u2028替换,U+2029用\u2029替换。

HTML转义字符:完整列表:http://www.theukwebdesigncompany.com/articles/entity-escape-characters.php

因此,当紧跟可能开始字符引用的任何内容时,您需要转义<或&。关于和号的规则是针对带引号的属性的唯一规则,因为匹配的引号是唯一能终止属性的东西。但是,如果您不想在那里终止属性值,请转义引号。

更改为UTF-8意味着重新保存文件:

在页面上使用字符编码UTF-8可以避免大多数转义,并且只需处理字符即可。但是,请注意,要更改文档的编码,仅更改页面或服务器顶部的编码声明是不够的。您需要以该编码重新保存文档。要了解如何使用应用程序进行此操作,请阅读设置Web作者ing应用程序中的编码。

不可见或模糊字符:

转义的一个特别有用的作用是表示在演示中是不可见或模糊的字符。

一个例子是Unicode字符U+200F从右到左的标记。此字符可用于澄清双向文本的方向性(例如,当使用阿拉伯语或希伯来语脚本时)。但是,它没有图形形式,因此很难看出这些字符在文本中的位置,如果遗忘或丢失,则可能在后期编辑期间产生意外结果。改为使用 ‏(或其数字字符引用等效物 ‏)可以轻松找到这些字符。

一个不明确的字符的例子是U+00A0不间断空格。这种类型的空格防止换行,但在用作字符时看起来与其他任何空格都一样。使用 可以清楚地显示此类空格出现在文本中的位置。


5

如果你想在JavaScript中转义一段标记字符串,有以下方法:

或者,如果你不想引入依赖项,可以使用相同的方法,但由于它使用split/map/join而不是charCodeAt/substring,所以略微慢一些。

function escapeMarkup (dangerousInput) {
  const dangerousString = String(dangerousInput);
  const matchHtmlRegExp = /["'&<>]/;
  const match = matchHtmlRegExp.exec(dangerousString);
  if (!match) {
    return dangerousInput;
  }

  const encodedSymbolMap = {
    '"': '&quot;',
    '\'': '&#39;',
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;'
  };
  const dangerousCharacters = dangerousString.split('');
  const safeCharacters = dangerousCharacters.map(function (character) {
    return encodedSymbolMap[character] || character;
  });
  const safeString = safeCharacters.join('');
  return safeString;
}

3
确切的答案取决于上下文。通常情况下,这些字符必须不存在(HTML 5.2 §3.2.4.2.5):
引用块:

文本节点和属性值必须由Unicode字符组成,不能包含U+0000字符,不能包含永久未定义的Unicode字符(非字符),且不能包含除空格字符以外的控制字符。根据其精确上下文,本规范对Text节点和属性值的确切值包括额外的约束。

对于HTML中的元素,文本内容模型的约束还取决于元素的类型。例如,在textarea元素中的"<"在HTML中不需要转义,因为textarea是一个可转义的纯文本元素。

这些限制分散在规范中。例如,属性值(§8.1.2.3)不能包含模棱两可的&符号,并且必须为空、在单引号中(因此不能包含U+0027 APOSTROPHE字符')、在双引号中(不能包含U+0022 QUOTATION MARK字符")或未加引号 - 具有以下限制: 引用块:

... 不能包含任何文字空格字符、任何U+0022 QUOTATION MARK字符(")、U+0027 APOSTROPHE字符(')、U+003D EQUALS SIGN字符(=)、U+003C LESS-THAN SIGN字符(<)、U+003E GREATER-THAN SIGN字符(>) 或 U+0060 GRAVE ACCENT字符(`),且不能为空字符串。


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