常量
HTML_ESCAPE | = | { "&" => "&", ">" => ">", "<" => "<", '"' => """, "'" => "'" } |
HTML_ESCAPE_ONCE_REGEXP | = | /["><']|&(?!([a-zA-Z]+|(#\d+)|(#[xX][\dA-Fa-f]+));)/ |
INVALID_TAG_NAME_FOLLOWING_REGEXP | = | /[^#{TAG_NAME_FOLLOWING_CODEPOINTS}]/ |
INVALID_TAG_NAME_START_REGEXP | = | /[^#{TAG_NAME_START_CODEPOINTS}]/ |
SAFE_XML_TAG_NAME_REGEXP | = | /\A[#{TAG_NAME_START_CODEPOINTS}][#{TAG_NAME_FOLLOWING_CODEPOINTS}]*\z/ |
TAG_NAME_FOLLOWING_CODEPOINTS | = | "#{TAG_NAME_START_CODEPOINTS}\\-.0-9\u{B7}\u{0300}-\u{036F}\u{203F}-\u{2040}" |
TAG_NAME_REPLACEMENT_CHAR | = | "_" |
TAG_NAME_START_CODEPOINTS | = | "@:A-Z_a-z\u{C0}-\u{D6}\u{D8}-\u{F6}\u{F8}-\u{2FF}\u{370}-\u{37D}\u{37F}-\u{1FFF}" \ "\u{200C}-\u{200D}\u{2070}-\u{218F}\u{2C00}-\u{2FEF}\u{3001}-\u{D7FF}\u{F900}-\u{FDCF}" \ "\u{FDF0}-\u{FFFD}\u{10000}-\u{EFFFF}" |
遵循 XML 要求:www.w3.org/TR/REC-xml/#NT-Name |
类公共方法
html_escape_once(s) 链接
一种实用方法,用于转义 HTML,而不影响现有转义实体。
html_escape_once('1 < 2 & 3')
# => "1 < 2 & 3"
html_escape_once('<< Accept & Checkout')
# => "<< Accept & Checkout"
源代码:显示 | 在 GitHub 上
# File activesupport/lib/active_support/core_ext/erb/util.rb, line 63 def html_escape_once(s) ActiveSupport::Multibyte::Unicode.tidy_bytes(s.to_s).gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE).html_safe end
json_escape(s) 链接
一种实用方法,用于转义 JSON 字符串中的 HTML 实体。具体来说,&、> 和 < 字符将替换为等效的 unicode 转义形式 - u0026、u003e 和 u003c。Unicode 序列 u2028 和 u2029 也将被转义,因为它们在一些 JavaScript 引擎中被视为换行符。这些序列在 JSON 字符串的上下文中与原始字符具有相同的含义,因此假设输入是一个有效且格式良好的 JSON 值,则输出在解析时将具有等效的含义
json = JSON.generate({ name: "</script><script>alert('PWNED!!!')</script>"})
# => "{\"name\":\"</script><script>alert('PWNED!!!')</script>\"}"
json_escape(json)
# => "{\"name\":\"\\u003C/script\\u003E\\u003Cscript\\u003Ealert('PWNED!!!')\\u003C/script\\u003E\"}"
JSON.parse(json) == JSON.parse(json_escape(json))
# => true
此方法的预期用例是在将 JSON 字符串包含在脚本标记内之前对其进行转义,以避免 XSS 漏洞
<script>
var currentUser = <%= raw json_escape(current_user.to_json) %>;
</script>
必须对 json_escape
的结果进行 raw
处理,这样引号才不会被转换为 "
实体。json_escape
不会自动将结果标记为 HTML 安全,因为原始值不适合在 HTML 属性中使用。
如果下游要将 JSON 插入 DOM,请注意是否通过 html()
插入。大多数 jQuery 插件都会这样做。如果是这种情况,请务必对 JSON 返回的任何用户生成的内容进行 html_escape
或 sanitize
处理。
如果您需要在 HTML 中的其他位置输出 JSON,您可以执行类似的操作,因为任何不安全字符(包括引号)都会自动为您转义
<div data-user-info="<%= current_user.to_json %>">...</div>
警告:此帮助器仅适用于有效的 JSON。将其用于非 JSON 值将产生严重的 XSS 漏洞。例如,如果您用用户输入替换上述示例中的 current_user.to_json
,则浏览器会愉快地将该字符串作为 JavaScript 进行 eval()
。
此方法中执行的转义与当 ActiveSupport.escape_html_entities_in_json
设置为 true 时在 Active Support JSON 编码器中执行的转义相同。由于此转换是幂等的,因此即使 ActiveSupport.escape_html_entities_in_json
已经为 true,也可以应用此帮助器。
因此,当您不确定 ActiveSupport.escape_html_entities_in_json
是否已启用,或者不确定 JSON 字符串的来源时,建议您始终应用此帮助器(其他库,例如 JSON gem,默认情况下不提供此类保护;此外,某些 gem 可能覆盖 to_json
以绕过 Active Support 的编码器)。
来源:显示 | 在 GitHub 上
# File activesupport/lib/active_support/core_ext/erb/util.rb, line 124 def json_escape(s) result = s.to_s.dup result.gsub!(">", '\u003e') result.gsub!("<", '\u003c') result.gsub!("&", '\u0026') result.gsub!("\u2028", '\u2028') result.gsub!("\u2029", '\u2029') s.html_safe? ? result.html_safe : result end
xml_name_escape(name) 链接
用于转义标签和属性名称的 XML 名称的实用方法。
xml_name_escape('1 < 2 & 3')
# => "1___2___3"
它遵循规范的要求:www.w3.org/TR/REC-xml/#NT-Name
来源:显示 | 在 GitHub 上
# File activesupport/lib/active_support/core_ext/erb/util.rb, line 142 def xml_name_escape(name) name = name.to_s return "" if name.blank? return name if name.match?(SAFE_XML_TAG_NAME_REGEXP) starting_char = name[0] starting_char.gsub!(INVALID_TAG_NAME_START_REGEXP, TAG_NAME_REPLACEMENT_CHAR) return starting_char if name.size == 1 following_chars = name[1..-1] following_chars.gsub!(INVALID_TAG_NAME_FOLLOWING_REGEXP, TAG_NAME_REPLACEMENT_CHAR) starting_char << following_chars end