Why Base64 in Basic Authentication
为什么在"授权"标头中使用Base64对生成的" username:password"字符串文字进行编码? 它的背景是什么?
要理解以下内容,您应该对"字符集"和"字符编码"之间的区别有清楚的了解。
另外,请记住,Base64是一种编码,而编码不是加密。 Base64中编码的任何内容都易于解码。
最重要的是,Base64编码可确保user:pass字符都是ASCII字符集和ASCII编码的一部分。 HTTP Basic auth中的user:pass是Authorization标头字段值的一部分。 HTTP标头值是ASCII(或扩展ASCII)编码/解码的。因此,当您对User:pass进行Base64编码时,请确保它是ASCII,因此是有效的标头字段值。
Base64编码还给明文user:pass至少增加了某种混淆。同样,这不是加密。但是,它确实阻止了正常的人类阅读用户:一眼就能通过。从安全角度来看,这似乎几乎毫无意义,并且由于以下背景信息,我仅将其包括在内。
一些背景
如果看一下RFC 2616(现在已过时)和RFC 2617,您会发现它们分别将头字段值和Basic auth user:pass定义为TEXT;即ISO-8859-1 OCTECT(ISO-8859-1是8位扩展ASCII编码)。这很奇怪,因为它似乎使作者希望符合要求的user:pass应该使用与HTTP标头所需的字符集/编码相同的字符集/编码,在这种情况下,Base64编码看起来似乎毫无意义,除了琐碎的混淆。
也就是说,很难相信那些RFC的作者没有想到用户名/密码使用非ASCII(非ISO-8859-1)字符集。假设他们有非ASCII用户:通行证,他们可能一直担心如何在所有ASCII标头集的中间包含/维护/传输非ASCII字节。 Base64编码user:pass当然可以很好地解决该问题。使用Base64还有更多规范的理由-使数据传输更加可靠。我的理解是HTTP是8位纯净的。即使标头以ASCII形式提供,我也不认为user:pass的Base64编码是为了使其传输更加可靠。
不问原始作者,我不确定我们是否会这是朱利安·雷施克(Julian Reschke)关于这个话题的有趣评论。他是RFC 5987,超文本传输??协议(HTTP)标头字段参数的字符集和语言编码的作者。他还对HTTP RFC进行了大量工作,包括最新的HTTP 1.1 RFC检修。
当前处理HTTP标头编码的HTTP 1.1 RFC RFC 7230,现在建议标头使用USASCII(又名ASCII,7位ASCII)。 RFC 5987定义了标头参数编码规范-大概有些人正在使用它。 RFC 7235是HTTP身份验证上RFC 2617的最新更新。
这是userid-password元组在编码之前的生产规则:
1 | userid-password = [ token ]":" *TEXT |
在这里令牌指定如下:
1 | token = 1* |
这基本上是32到126之间的任何US-ASCII字符,但没有一些特殊字符(
TEXT指定如下:
1 2 | TEXT = <any OCTET except CTLs, but including LWS> |
这基本上是任何八位字节(0–255)序列,但控制字符(代码点0–31、127)除外,但包括线性空格序列,该序列是一个或多个空格或水平制表符,可能在CRLF序列之后:
1 | LWS = [CRLF] 1*( SP | HT ) |
尽管这不会破坏标题字段的值,但LWS的语义与单个空格相同:
All linear
whitespace, including folding, has the same semantics as SP.
为了保持这样的顺序,在将字符串作为字段值放置之前先对其进行编码。