HTTP 查询字符串中必须转义哪些字符?

Posted

技术标签:

【中文标题】HTTP 查询字符串中必须转义哪些字符?【英文标题】:What characters must be escaped in an HTTP query string? 【发布时间】:2021-11-14 13:10:52 【问题描述】:

此问题涉及 URL 查询字符串部分中的字符,这些字符出现在 ? 标记字符之后。

根据Wikipedia,某些字符保持原样,而其他字符则被编码(通常使用% 转义序列)。

我一直在尝试将其追踪到实际规范,以便我了解该 Wikipedia 页面中每个要点背后的理由。

矛盾例子1:

html specification 表示将空间编码为+,并将其余部分推迟到RFC1738。然而,这个 RFC 说 ~ 是不安全的,而且“[a]ll 不安全的字符必须始终在 URL 中进行编码”。这似乎与***相矛盾。

实际上,IE8 在它生成的查询字符串中编码~,而 FF3 保持原样。

矛盾例子2:

***声明它未提及的所有字符都必须进行编码。 ! 未在***中提及。但是RFC1738 声明! 是一个“特殊”字符并且“可以未编码使用”。这似乎与***说它必须被编码相矛盾。

实际上,IE8 在它生成的查询字符串中编码!,而 FF3 保持原样。

我知道这样做的寓意可能是对那些在 Wikipedia 和规范之间存在疑问的字符进行编码。甚至可能会编码所有不是 [A-Za-z0-9] 的东西。我只是想知道这方面的实际标准。

结论

***上描述的算法精确地编码那些不是RFC3986 unreserved characters 的字符。也就是说,它对除字母数字和-._~ 之外的所有字符进行编码。作为一种特殊情况,根据 RFC3986,空格被编码为 + 而不是 %20

某些应用程序使用较旧的 RFC。作为比较,RFC2396 unreserved characters 是字母数字,!'()*-._~

为了比较,HTML5 working draft algorithm 对除字母数字和*-._ 之外的所有字符进行编码。空间的特殊情况编码仍然是+。显着的区别是* 未编码,~ 已编码。 (从技术上讲,* 的这种处理与 RFC3986 兼容,即使 *reserved 中,因为它在 sub-delims 中,而在 query 生产中是允许的。)

【问题讨论】:

***不是一个标准机构。如有疑问,请使用标准。 @John - 尽管使用 正确 标准很重要。在这种情况下是 3986,而不是旧的 1738。 What every web developer must know about URL encoding(“每个部分的保留字符不同”部分在此上下文中非常相关)。 【参考方案1】:

答案在 RFC 3986 文档中,特别是 Section 3.4。

查询组件由第一个问题表示 标记 ("?") 字符并以数字符号 ("#") 字符结尾 或在 URI 的末尾。

...

字符斜线(“/”)和问号(“?”)可能代表数据 在查询组件中。

从技术上讲,RFC 3986-3.4 将查询组件定义为:

query       = *( pchar / "/" / "?" )

此语法意味着查询可以包括来自pchar 以及/? 的所有字符。 pchar 指的是另一种路径字符规范。有帮助的是,RFC 3986 的Appendix A 列出了相关的 ABNF 定义,最值得注意的是:

query         = *( pchar / "/" / "?" )
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

因此,除了所有字母数字和百分比编码字符之外,查询还可以合法地包含以下未编码字符:

/ ? : @ - . _ ~ ! $ & ' ( ) * + , ; =

当然,您可能需要记住,“=”和“&”通常在查询中具有特殊意义。

【讨论】:

注意:除了=&之外,服务器端可能会限制其他合法未编码的查询字符串字符,例如php中的.(点),它将被_(下划线)替换在$_GET$_POST。请参阅:***.com/questions/68651/…(也有解决方法)。 好吧,那么 PHP 用户需要在 $_SERVER['QUERY_STRING'] 上使用符合规范的解析器,而不是依赖像 $_GET 这样的损坏功能。

以上是关于HTTP 查询字符串中必须转义哪些字符?的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式中必须转义哪些特殊字符?

正则表达式中必须转义哪些特殊字符?

正则表达式中必须转义哪些特殊字符?

Sql Server LIKE 查询中需要转义哪些字符[重复]

php mysql转义特殊字符的函数都有哪些

Apache2重写查询字符串转义两次