我应该使用什么编码进行HTTP基本身份验证?

时间:2011-08-30 11:18:16

标签: http basic-authentication

RFC2617表示将用户名和密码编码为base64,但没有说明在创建用于输入base64算法的八位字节时要使用的字符编码。

我应该假设US-ASCII还是UTF8?或者有人已经在某个地方解决了这个问题?

4 个答案:

答案 0 :(得分:56)

原始规范 - RFC 2617

RFC 2617可以读作“ISO-8859-1”或“undefined”。你的选择。众所周知,许多服务器使用ISO-8859-1(喜欢或不喜欢),并且在发送其他内容时会失败。所以可能唯一安全的选择就是坚持使用ASCII。

有关更多信息和解决问题的建议,请参阅草案"An Encoding Parameter for HTTP Basic Authentication"(构成RFC 7617的基础)。

新增 - RFC 7617

自2015年以来,有RFC 7617,它废弃了RFC 2617.与旧的RFC相比,新的RFC明确定义了用于用户名和密码的字符编码。

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

完整版:

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

浏览器支持

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

  • Chrome似乎也使用UTF-8
  • Internet Explorer不使用UTF-8(issue #11879588
  • Firefox正在尝试针对v59(bug 1419658
  • 目前计划的更改

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

答案 1 :(得分:36)

简答:iso-8859-1,除非按照RFC2047(MIME)使用编码字。

更长的解释:

RFC2617, section 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

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

  

此规范是HTTP / 1.1规范2的配套产品。   它使用该文档的增强BNF部分2.1,并依赖于   该文件中定义的非终端和其他方面   HTTP / 1.1规范。

RFC2616, section 2.1定义 TEXT (强调我的):

  

TEXT规则仅用于描述性字段内容和值   不打算由消息解析器解释。话   * TEXT可以包含除字符集以外的字符    ISO-8859-1 仅在根据RFC 2047的规则进行编码时。

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

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

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

在这种情况下,根据iso-8859-15,单词中的欧元符号将被编码为0xA4。我的理解是你应该检查这些编码的单词分隔符,然后根据指定的编码解码里面的单词。如果不这样做,您会认为密码为=?iso-8859-15?q?T¤ST?=(请注意,0xA4在解释为iso-8859-1时会被解码为¤

这是我的理解,我找不到比这些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中最重要的一点)。

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

答案 2 :(得分:4)

如果您对在登录提示符下输入非ascii字符时浏览器的操作感兴趣,我只是尝试使用Firefox。

通过获取每个unicode值的最低有效字节,似乎懒惰地将everithing转换为ISO-8859-1,例如:

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

编码与:

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

0x5a 0x3a 0x4e base64-&gt; WjpO

答案 3 :(得分:4)

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

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