HTTP基本身份验证应使用哪种编码?


Answers:


72

原始规格-RFC 2617

RFC 2617可以读取为“ ISO-8859-1”或“未定义”。你的选择。众所周知,许多服务器都使用ISO-8859-1(无论是否喜欢),并且在发送其他内容时会失败。因此,可能唯一安全的选择是坚持使用ASCII。

有关更多信息和解决此问题的建议,请参阅“ HTTP基本身份验证的编码参数”草稿(构成RFC 7617的基础)。

新增-RFC 7617

自2015年以来,存在RFC 7617,它取代了RFC2617。与旧RFC相比,新RFC明确定义了用于用户名和密码的字符编码。

  • 默认编码仍未定义。仅要求Is与US-ASCII兼容(这意味着它像UTF-8一样将ASCII字节映射到ASCII字节)。
  • 服务器可以选择charset="UTF-8"在其质询中发送一个附加的身份验证参数,如下所示:
    WWW-Authenticate: Basic realm="myChosenRealm", charset="UTF-8"
    这表明服务器将接受用户名/密码中的非ASCII字符,并且希望它们以UTF-8编码(特别是规范化形式C) 。请注意,仅允许使用UTF-8。

完整版本:

阅读规范。如果包含其他详细信息,例如确切的编码过程以及应支持的Unicode代码点列表。

浏览器支持

从2018年开始,如果用户输入用户名或密码的非ASCII字符(即使服务器未使用该charset参数),现代浏览器通常将默认为UTF-8 。

  • Chrome似乎也使用UTF-8
  • Internet Explorer不使用UTF-8(问题#11879588
  • Firefox正在试验当前计划用于v59的更改(错误1419658

领域

即使在RFC 7617中,领域参数仍仅支持ASCII字符。


谢谢朱利安。我碰到了那个建议,但似乎已经过期,并且没有进一步发展。太糟糕了:
。– Dobes Vandermeer

1
您的答案一定是最好的。我可以肯定地将其解释为ASCII,如果幸运的话,也可以是ISO-8859-1。
Dobes Vandermeer

该提案最新版本04(似乎同时在今天发布)似乎于2012
Michiel van Oosterhout

答案是过时的,因为它没有提到RFC7617。我进行了编辑以包括此内容。朱利安:希望你不介意。
sleske '18

糟糕-我刚刚意识到您实际上是RFC 7617的作者。现在我真的希望我不要对某些内容进行误编辑。
sleske '18

41

简短的答案:iso-8859-1,除非根据RFC2047(MIME)使用编码字。

更长的解释:

RFC2617第2节(HTTP身份验证)定义了基本凭证

basic-credentials = base64-user-pass
base64-user-pass  = <base64 encoding of user-pass, 
                     except not limited to 76 char/line>
user-pass         = userid ":" password
userid            = *<TEXT excluding ":">
password          = *TEXT

如果不参考RFC2616(HTTP 1.1)中的BNF定义(如上述内容),则不应阅读该规范:

该规范是HTTP / 1.1规范2的伴随。它使用了该文档的增强BNF第2.1节,并依赖于该文档中定义的非终端以及HTTP / 1.1规范的其他方面。

RFC2616第2.1节定义了TEXT(强调我的):

TEXT规则仅用于描述性字段内容和消息解析器不打算解释的值。仅当按照RFC 2047的规则进行编码时,* TEXT的单词才可以包含ISO-8859-1以外的字符集的字符 。

TEXT           = <any OCTET except CTLs, but including LWS>

因此,这绝对是iso-8859-1,除非您根据RFC2047(MIME pt.3)规则检测到其他编码:

// Username: Mike
// Password T€ST
Mike:=?iso-8859-15?q?T€ST?=

在这种情况下,单词中的欧元符号将0xA4按照iso-8859-15进行编码。据我了解,您应该检查这些编码的单词定界符,然后根据指定的编码对内部的单词进行解码。否则,您会认为密码是=?iso-8859-15?q?T¤ST?=(注意,当解释为iso-8859-1时0xA4会被解码为该密码¤)。

这是我的理解,我无法找到比这些RFC更明确的确认。而且其中有些似乎是矛盾的。例如,RFC2047(MIME,第3页)提出的4个目标之一是重新定义:

消息格式,以允许使用...字符集而不是US-ASCII的文本标题信息。

但是,RFC2616(HTTP 1.1)然后使用TEXT规则定义了标头,该标头默认为iso-8859-1。这是否意味着该标头中的每个单词都应该是一个编码单词(即=?...?=形式)?

同样重要的是,当前没有浏览器可以这样做。他们使用utf-8(Chrome,Opera),iso-8859-1(Safari),系统代码页(IE)或其他名称(例如,对于Firefox,仅来自utf-8的最高有效位)。

编辑:我刚刚意识到这个答案更多地从服务器端的角度看问题。


RFC 2047编码在这种情况下不适用。
朱利安·雷施克

@JulianReschke好吧,该规范明确指出“仅在根据RFC 2047的规则进行编码时”。我了解RFC2047中的规则可能不适用于HTTP标头,但在引用该规范时很明确。我添加了一个事实,即没有浏览器实际执行此操作。
Michiel van Oosterhout 2012年

4
HTTPbis规范将不再提及RFC 2047。
朱利安·雷施克

非常详细的文章,谢谢@MichielvanOosterhout!
ToastyMallows's

5

除了RFC,在Spring框架中BasicAuthenticationFilter该类的默认值为UTF-8

我相信选择该标记的原因是UTF-8能够编码所有可能的字符,而ISO-8859-1(或ASCII)则不能。尝试将用户名/密码与系统中不支持的字符一起使用会导致行为中断或(可能更糟)降低安全性。


1
好吧,如果对方不知道,使用UTF-8并不会有所帮助。因此,如果Spring框架实现了< greenbytes.de/tech/webdav/rfc7617.html#rfc.section.2.1 >
Julian Reschke,

1
@JulianReschke我介绍了它是如何在最常见的框架之一中实现的,并可能是其原因。不要开枪!
holmis83 '17

4

如果您对在登录提示符下输入非ASCII字符时浏览器的功能感兴趣,我就尝试使用Firefox。

通过采用每个unicode值的最低有效字节,似乎将所有内容延迟转换为ISO-8859-1,例如:

User: 豚 (\u8c5a)
Password: 虎 (\u864e)

编码与:

User: Z (\u005a)
Password: N (\u004e)

0x5a 0x3a 0x4e base64-> WjpO


1
是的,这是Firefox中的旧行为。它已更改(似乎在V57中),现在改为使用UTF-8。
sleske '18

1
V59,而不是V57。目前处于beta测试中。
朱利安·雷施克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.