[自用][中文翻译] RFC2617 HTTP摘要认证(节选)

@Ta 2022-01-15发布,2022-01-15修改 691点击
被下沉
评论关闭
以前自己翻译的RFC,只有一部分。

RFC2617 HTTP摘要认证(节选).pdf(305.39 KB)

RFC2617 HTTP摘要认证(节选).doc(107.33 KB)

以下为txt内容预览(排版不正确):

网络工作组
RFC 2617
废除:2069
分类:标准跟踪

J. Franks
西北大学(美国)
P. Hallam-Baker
威瑞信公司
J. Hostetler
AbiSource, Inc.
S. Lawrence
Agranat Systems, Inc.
P. Leach
微软公司
A. Luotonen
网景通信公司
L. Stewart
Open Market, Inc.
1999年6月

HTTP认证:基本和摘要访问认证(节选)
本备忘录的状态
   本文档为Internet社区描述了一种Internet标准跟踪协议,还需讨论和建议以便进行改善。请查看最新版本的“Internet正式协议标准”(STD 1)了解本协议的标准化进程和状态。本备忘录的传播不受限制。
版权声明
   版权所有 (C) Internet协会(1999)。所有权利保留。
摘    要
   “HTTP/1.0”中包含了基本访问认证方案(Basic Access Authentication scheme),该方案不是安全的用户认证方法(除非与其他安全方案联合使用,如SSL[5]),因为其用户名和密码是以明文方式在网络上传送的。
   本文档提供了两种HTTP认证框架的规范:原始的基本认证方案,和一种基于密码学散列的认证方案,称为“摘要访问认证”。因此,本文档也打算做为RFC 2069 [6]的替代。因为在 RFC 2069 发布后发现了一些问题,许多原本在RFC 2069 中定义的元素已经从本文档中移除。为了兼容性考虑,添加了一些新元素,这些新元素被设计为可选的,但强烈建议实现它们。
   和基本认证一样,摘要访问认证也是通过一个通信双方都知道的共享密钥(密码)来进行验证的;但与基本认证不同,使用摘要认证时不需要明文发送密码,也就避免了这个基本认证最大的缺点。正如其他大多数认证协议那样,该协议最大的风险源不是协议本身,而是使用该协议的程序及使用策略。
目   录
本备忘录的状态 I
版权声明 I
摘    要 II
1访问认证 - 1 -
1.1对HTTP/1.1规范的依赖 - 1 -
1.2访问认证框架 - 1 -
2基本认证方案 - 3 -
3摘要访问认证方案 - 5 -
3.1介绍 - 5 -
3.1.1目的 - 5 -
3.1.2操作概述 - 5 -
3.1.3摘要值的表示方法 - 5 -
3.1.4局限性 - 5 -
3.2 摘要头规格说明 - 6 -
3.2.1 “WWW-Authenticate”响应头 - 6 -
3.2.2“Authorization”请求头 - 9 -
3.2.3“Authentication-Info”响应头 - 14 -
3.3摘要操作 - 15 -
3.4安全协议协商 - 16 -
3.5例子 - 17 -
3.6“Proxy-Authenticate”和“Proxy-Authorization”头 - 17 -
参 考 文 献 - 19 -

1访问认证
1.1对HTTP/1.1规范的依赖
   本规范与HTTP/1.1规范[2]一起使用。本规范使用定义于HTTP/1.1规范 2.1小节的扩展巴科斯范式(Augmented BNF),并依赖HTTP/1.1规范对“非终端”(Non-terminals)的定义及对其他方面的描述。
1.2访问认证框架
   HTTP提供了一种简单的“质询-响应”认证机制,它可以被服务器用来质询客户端的请求,也可以被客户端用来提供认证信息。它使用一个可扩展的,大小写敏感的标识符来指明认证方案,后面跟着一系列该认证方案所需的逗号分隔的“属性-值”对。
       认证方案 = 标识符
       认证参数 = 标识符 "=" ( 标识符 | 双引号字符串 )
   401(未授权)响应消息被原始服务器用来对客户端发起认证质询,该响应必须包含一个“WWW-Authenticate”头域,头域内包含至少一个适用于所请求资源的质询。407(代理要求认证)响应消息被代理服务器用来对客户端发起认证质询,该响应必须包含一个“Proxy-Authenticate”头域,头域内包含至少一个适用于代理所请求资源的质询。
       质询 = 认证方案 1*空白 1#认证参数
   注意:用户代理解析 WWW-Authenticate 和 Proxy-Authenticate 头域时,在碰到含有多个质询或多个 WWW-Authenticate 头域时要特别小心,因为一个质询本身就包含了以逗号分隔的多个认证参数。
   认证参数“区域”(realm)在所有的认证方案中都有定义:
       区域   = "realm" "=" 区域值
       区域值 = 双引号字符串
   “区域”指令(大小写敏感)在所有涉及质询的认证方案中都要用到,区域值(大小写敏感)要与被访问服务器的根URL的规范写法(即绝对路径为空的服务器的绝对URI,见[2]的5.1.2小节)联合使用,以定义受保护的区间。“区域”指令允许将服务器上的受保护资源分成若干个区间,每个区间都有自己的认证方案和(或)认证数据库。区域值是字符串,通常由原始服务器分配,针对某些认证方案可能还有附加的语法规范。注意,可能存在多个质询的认证方案相同,但区域不同的情况。
   用户代理在收到401(未授权)响应时,会希望得到原始服务器的认证(通常如此,但非必须),此时,用户代理可以在请求中加入“Authorization”头域。用户代理在收到407(代理需要认证)响应时,会希望得到代理服务器的认证(通常如此,但非必须),此时,用户代理在请求中加入“Proxy-Authorization”头域。“Authorization”和“Proxy-Authorization”头域的值都由认证凭证组成,该认证凭证包含了客户端在所请求资源所在区域的认证信息。如果有多个质询可供选择,用户代理必须选择响应它自身认为的强度最高的认证方案,并通过和用户交互取得所需的认证凭证。
       认证凭证 = 认证方案 #认证参数
   注意:许多浏览器只支持基本认证方案,并只在“Basic”排在认证方案的第一位时才能识别。如果要让尽可能多的浏览器能够访问,服务器应只包含基本认证方案。
   受保护区间决定了认证凭证可以自动应用的范围。如果上一个请求已经通过认证,相同的认证凭证可以在认证方案、认证参数,和(或)用户配置决定的一段时间内被后续请求重用。除非认证方案有特别指定,否则单个受保护区间不能扩展到其所在服务器以外的范围。
   如果原始服务器不想接受请求中的认证凭证,它应该返回401(未授权)响应。该响应必须包含一个“WWW-Authenticate”头域,头域内包含至少一个(可能是新的)适用于所请求资源的质询。如果代理不想接受请求中的认证凭证,它应该返回407(代理需要认证)响应。该响应必须包含一个“Proxy-Authenticate”头域,头域内包含至少一个(可能是新的)适用于代理所请求资源的质询。
   HTTP协议的访问认证并不限于这种简单的“质询-响应”机制,还可以使用其他方法,比如传输层加密或消息体加密,并通过附加的头域指定认证信息。但这些额外的机制不在本规范的讨论范围。
   代理服务器必须完全透明地处理原始服务器对用户代理的认证。这意味着,代理服务器必须原封不动的转发“WWW-Authenticate”和“Authorization”头信息,这方面的规定见[2]的14.8小节。“Proxy-Authenticate”和“Proxy-Authorization”头域都是逐跳头(Hop-by-hop headers,见[2]的13.5.1小节)。

2基本认证方案
   基本("basic")认证方案的工作模式为,客户端在每个区域内必须通过一个用户ID和一个密码来认证它自己。“区域”值应该被视为不透明的字符串,只用于在服务器端与该服务器上的其他区域进行区分。只有在请求URI所在的受保护区间内,客户端提供的用户ID和密码通过验证,服务器才提供相应的服务。基本认证方案没有可选参数。
   在基本认证方案中,上述框架的应用形式如下:
       质询     = "Basic" 区域
       认证凭证 = "Basic" 基本认证凭证
   在收到未经认证的对受保护区间内的URI的请求时,原始服务器可以在响应中包含一个类似这样的质询:
       WWW-Authenticate: Basic realm="WallyWorld"
   在这里,“WallyWorld”是服务器分配的用于标识请求URI所在的受保护区间的字符串。代理服务器也可以在“Proxy-Authenticate”头域内包含这种的质询。
   为了接受认证,客户端发送一个字符串做为认证凭证,该字符串由用户ID和密码连接而成,中间用单个半角冒号(“:”)分隔,并进行 base64[7]编码。
       基本认证凭证           = base64编码的用户名密码
       base64编码的用户名密码 = <base64[4]编码的用户名密码,
                      注意没有每行76字符的限制>
       用户名密码 = 用户ID ":" 密码
       用户ID    = *<文本,不包括":">
       密码       = *文本
   用户ID可能是大小写敏感的。
   如果用户代理想发送的用户ID为"Aladdin",密码为"open sesame",它应该使用如下头域:
       Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
   对某个特定质询的请求URI来说,客户端应该假定所有路径部分与它相同或比它更深的请求URI都和它属于同一个受保护空间,该受保护空间的基本认证区域就是该质询的认证区域。在没有接到服务器发送的其他质询的情况下,客户端可以在请求该受保护空间内的资源时,先行发送与之前一样的“Authorization”头信息。同样的,在客户端发送认证请求给代理服务器之后,它也可以在代理没有发送其他质询的情况下重用“Proxy-Authorization”头域的用户名和密码。参考第4小节关于基本认证方案的安全性考虑。


3摘要访问认证方案
3.1介绍
3.1.1目的
   "HTTP/1.0"中包含了基本访问认证方案(Basic Access Authentication scheme),该方案不是安全的用户认证方法(除非与其他安全方案联合使用,如SSL[5]),因为其用户名和密码是以明文方式在网络上传送的。
   摘要访问认证方案不是WWW安全问题的最终解决方案。该方案不提供消息内容加密,其目的只是创建一个简单的认证方法,以弥补基本认证方案中存在的大部分严重漏洞。
3.1.2操作概述
   和基本认证一样,摘要认证也基于简单的“质询-响应”范式。摘要认证使用随机值来质询,合法的回应包含对用户名、密码、给定的随机值、HTTP方法、请求URI的校验和(默认为MD5校验和),因此,密码不会以明文方式传送。和基本认证一样,用户名和密码必须被预处理为什么格式不在本文档的讨论范围之内。
3.1.3摘要值的表示方法
   可选的头信息允许服务器指定用于创建校验和或摘要的算法。MD5是默认的算法,也是本文档唯一提及的算法。
   在本文档中,128位的MD5摘要由32个可打印的ASCII码字符表示。128位摘要由高位到低位,每4位用一个ASCII字符表示。每四位所对应的ASCII码字符就是这个四位的二进制数的十六进制表示,即“0123456789abcdef”。也就是说,二进制 0000 用字符“0”表示,0001 用“1”表示,直到最后的 1111 用“f”表示。
3.1.4局限性
   本文档中描述的摘要认证方案存在许多已知的局限性,它只是对基本认证方案的替代,除此之外并无更多。它是基于密码的认证系统,在服务器端也要面对任何其它密码系统同样存在的问题。本协议并没有为最初用户和服务器间的密码建立提供安全做法。
   用户和开发者都应注意,该协议并不象Kerberos或任何客户端的私钥方案那样安全。但是,即便它一无是处,总还比在telnet、ftp用的机制好一些,当然,也比基本方案安全。
3.2 摘要头规格说明
   摘要认证在概念上与基本认证类似,修改后的“WWW-Authenticate”头信息格式在下面给出。此外,还有一个新的“Authentication-Info”头域也在下面给出。
3.2.1 “WWW-Authenticate”响应头
   服务器在收到访问受保护对象的请求时,如果请求不包含可被接受的“Authorization”头,服务器会响应“401 未授权”状态码,并包含在先前框架里定义的“WWW-Authenticate”头域。在摘要认证方案中,该头域的格式如下:
       质询        = "Digest" 摘要质询
       摘要质询    = 1#( 区域 |  [域]  | 随机值 |
                 [不透明值]  |  [陈旧性]  |  [算法] |
                 [保护质量选项]  |  [认证参数]  )
       域           = "domain" "=" <"> URI ( 1*空白 URI ) <">
       URI         = 绝对URI | 绝对路径
       随机值       = "nonce" "=" 随机内容
       随机内容     = 双引号字符串
       不透明值     = "opaque" "=" 双引号字符串
       陈旧性       = "stale" "=" ( "true" | "false" )
       算法         = "algorithm" "=" ( "MD5" | "MD5-sess" | token )
       保护质量选项 = "qop" "=" <"> 1#保护质量值 <">
       保护质量值   = "auth" | "auth-int" | 标识符
   
上述指令的意义如下:
   (1)区域
   显示给用户看的字符串,这样他们就知道该使用哪个用户名和密码了。该字符串应该至少包含一个执行认证的主机名,以及附加对可以访问的用户群体的附加指示,例如"registered_users@gotham.news.com"。
   (2)域
   一个双引号包围的,空白分隔的URI列表(其规范见RFC XURI[7]),定义了受保护区间。如果URI采用绝对路径,它被视为该服务器标准根URL下的绝对路径(参见上面的第1.2节)。列表中的绝对URI可以用来表示该认证也可用于访问另一服务器。客户端可以用该列表去决定对哪些URI发送相同的认证信息:以任何在此列表中出现的URI做为前缀的URI,都属于同一个受保护区间(两者都转为绝对URI之后进行比较)。如果该指令未给出或者值为空,客户端应该假设受保护区间包括该响应服务器上的所有URI。
   该指令对“Proxy-Authenticate”头没有意义,因为对代理来说,受保护区间总是整个代理。如果该值出现,应该被忽略。
   (3)随机值
   服务器指定的数据字符串,应该在每个401响应产生时被唯一地生成。建议该字符串以base64或十六进制值的形式出现。特别要注意的是,因为该字符串出现在头域内时是被引号包围的,所以半角双引号不允许在字符串中出现。
   随机值的内容与实现有关,而实现的质量则取决于良好的选择。做为例子,一个随机值可以按照如下方法构造并进行base64编码:
       时间戳 H(时间戳 ":" ETag ":" 私钥)
   上面的表达式里,时间戳是由服务器产生的时间值或其他非重复值;Etag是HTTP与请求实体相关的ETag头的值;私钥是只有服务器才知道的值。在使用这种形式的随机值时,服务器在收到客户端的认证头之后,可以对散列部分进行重新计算,并在计算结果与从头域中收到的随机值不符或者时间戳不够新时拒绝该请求。通过这种方式,服务器可以限制随机值的有效时间范围。而ETag中的内容则能够防止对某个资源更新后的版本重放先前的认证请求。(注意:在随机值中包含客户端的IP地址看上去能够为服务器提供限制客户端重用随机值的能力,但是,这会影响代理池的正常工作,因为此时单个用户的请求可能通过池中的不同代理到达服务器。此外,伪造IP地址也不是十分困难。)
   为了防止重放攻击,实现可以选择不接受先前使用过的随机值或先前使用过的摘要。或者,实现可以选择在POST和PUT请求中使用一次性的随机值和摘要,并在GET请求中使用基于时间戳的摘要。有关安全性的更多细节参见本文档的第4小节。
   客户端应该把随机值视为不透明的。
   (4)不透明值
   由服务器指定的字符串数据,在请求同一受保护区间内的URI时,客户端应把该值通过“Authorization”头原封不动的返回给服务器。该值建议使用base64或十六进制形式表示。
   (5)陈旧性
   一个标识,用来指示客户端先前的请求因其随机值过期而被拒绝。如果陈旧性是TRUE(大小写不敏感),客户端可能希望用新的加密响应简单重试,而不需要麻烦用户去输入新的用户名和密码。服务器应该仅在收到一个随机值不合法但该随机值的摘要合法(意味着该客户端知道正确的用户名和密码)的请求时将该指令设置为TRUE。如果该指令是FALSE或其他非TRUE的值,或该指令没有出现,则意味着用户名和/或密码错误,需要重新输入。
   (6)算法
   一个字符串,用来指定产生摘要与校验和的算法。如果该指令没有指定,则假设是“MD5”算法。如果该指令指定的算法无法理解,该质询将被忽略(如果不止一个算法,另一个将被使用)。
   在本文中,通过摘要算法对数据“data”和秘密“secret”计算得到的字符串表示为 KD(secret, data),通过校验和算法由数据“data”生成的字符串表示为H(data)。符号 unq(X) 表示把双引号字符串X去掉双引号后的值。
   对 "MD5" 和 "MD5-sess" 算法来说:
       H(data) = MD5(data)
   并且
       KD(secret, data) = H(连接(secret, ":", data))
   也就是说,摘要就是对secret与data通过冒号连接一起的结果进行MD5运算后的值。而"MD5-sess"算法则允许其它第三方服务器参与鉴别。具体用法上的区别,参见 3.2.2的第(2)小节。
   (7)保护质量选项
   该指令是可选的,用于RFC 2069[6]的向后兼容,它应当被任何想要兼容RFC 2069的实现所使用。如果存在,它是带引号的一个或多个标识符组成的字符串,用来指示服务器支持的保护质量(Quality of Protection)值。”auth”值表示认证;”auth-int”表示具有完整性保护的认证。在应用了该选项时如何计算响应指令参见后面的描述。不能识别的选项必须被忽略。
   (8)认证参数
   该指令允许未来进行扩展,任何不能被识别的指令都必须被忽略。
3.2.2“Authorization”请求头
   客户端预期会重试请求,包含前述框架中的“Authorization”头信息,具体格式如下:
       认证凭证       = "Digest" 摘要响应
       摘要响应       = 1#( 用户名 | 区域 | 随机值 | 摘要uri |
                   响应 | [算法] | [客户端随机值] |
                   [不透明值] | [消息保护质量] |
                   [随机值统计] | [认证参数] )
       用户名         = "username" "=" 用户名内容
       用户名内容     = 双引号字符串
       摘要uri       = "uri" "=" 摘要uri内容
       摘要uri内容   = 请求uri ; 在 HTTP/1.1 中定义
       消息保护质量   = "qop" "=" 保护质量值
       客户端随机值   = "cnonce" "=" 客户端随机内容
       客户端随机内容 = 随机值
       随机值计数     = "nc" "=" 计数值
       计数值         = 8小写HEX
       响应           = "response" "=" 请求摘要
       请求摘要       = <"> 32小写HEX <">
       
小写HEX        = "0" | "1" | "2" | "3" |
 "4" | "5" | "6" | "7" |
 "8" | "9" | "a" | "b" |
 "c" | "d" | "e" | "f"
   “不透明值”和“算法”域里包含的必须是在该请求实体对应的“WWW-Authenticate”响应头中给出的值。
   
   上述指令的意义如下:
   (1)响应
   一个由32位十六进制数组成的字符串,用来证明用户知道密码。定义在下方给出。
   (2)用户名
   用户在特定区域的名称。
   (3)摘要uri
   从请求行得到的请求URI。备份到这里是因为在传输过程中代理服务器被允许改变请求行。
   (4)保护质量
   指示客户端对该消息应用的保护质量(Quality of Protection)。如果不为空,其值必须是服务器支持在“WWW-Authenticate”头中给出的几个值之一。这些值会对请求摘要的计算造成影响。注意,这是个单独的标识符,而不是像“WWW-Authenticate”中的那样是带引号的可选值列表。该指令是可选项,这是为了和RFC 2069[6]所规定的最小实现保持向后兼容。但是,如果服务器端通过在WWW- Authenticate头域中添加保护质量指令来表明该服务器支持保护质量,客户端就应该使用该指令。
   (5)客户端随机值
   当指定保护质量指令时(见上面),该指令必须要指定,而当服务器端没有在WWW-Authenticate头域中添加保护质量指令时,该指令必须不能指定。客户端随机内容是客户端提供的不透明双引号字符串,用来在客户端和服务器之间避免选择明文攻击,提供互相认证以及一定程度的消息完整性保护。详见下面的响应摘要值和请求摘要值的计算。
   
   (6)随机值计数
   当指定保护质量指令时(见上面),该指令必须要指定,而当服务器端没有在WWW-Authenticate头域中添加保护质量指令时,该指令必须不能指定。计数值用16进制表示,用来统计客户端发送的同一随机值的请求(包括当前请求)个数。例如,在得到随机值后的第一个请求中,客户端发送“nc=00000001”。其目的是允许服务器通过对此计数副本的维护来检测请求重放,即当同样的随机值计数出现第二次,说明该请求是重放的。详见下面的响应摘要值和请求摘要值的计算。
   (7)认证参数
   该指令允许未来进行扩展,任何不能被识别的指令都必须被忽略。
   
   如果指令或其值不正确,或者需要的指令没有给出,都会得到“400 请求错误”响应。如果请求摘要是非法的,登录失败应该被记入日志,因为在某个单独的客户端出现的重复登录失败可能意味着攻击者正试图猜测密码。
   前面定义的请求摘要指示了其编码方式,下面的定义将表明这些值是如何计算的:
   (1)请求摘要
如果"qop"(保护质量)值为"auth"或"auth-int":
请求摘要 = <"> < KD ( H(A1),    unq(随机值)
                ":" 计数值
                ":" unq(客户端随机内容)
                ":" unq(保护质量值)
                ":" H(A2)
                   ) > <">
   如果“qop”选项没有给出(与RFC 2069保持兼容):
       请求摘要 = <"> < KD ( H(A1), unq(随机值) ":" H(A2) ) > <">
   A1及A2的定义在下面。
   (2)A1
如果算法的值为"MD5"或未指定,则A1为:
       A1 = unq(用户名内容) ":" unq(区域值) ":" 密码
其中
       passwd = < 用户的密码 >
   如果算法值为"MD5-sess",则A1只要计算一次,即当客户端发出第一个请求,并从服务器收到WWW-Authenticate质询时计算。它使用该质询中的服务器随机值和客户端使用的第一个随机值来来构建A1:
       A1 = H( unq(用户名内容) ":" unq(区域值)
            ":" 密码 )
            ":" unq(随机值) ":" unq(客户端随机值)
   上式为随后的请求和回应的认证产生了一个“会话密钥”(session key),该密钥对于每个”认证会话”(authentication session)都是不同的,这样就减少了使用每个密钥进行哈希处理的次数(注意:关于认证会话更深层次的探讨见3.3节)。
   因为服务器只需要使用用户凭证的哈希值来产生A1值,因而该机制可允许第三方参与认证服务,这样WEB服务器就不再需要实际的密码值了。该协议的规范已经超出了本规范的内容范围。
   (3)A2
如果"qop"值为"auth"或没有给出,则A2为:
A2 = 请求方法 ":" 摘要uri值
如果"qop"值为"auth-int",则A2为:
A2 = 请求方法 ":" 摘要uri值 ":" H(请求实体)
   (4)指令值和双引号字符串
   注意,许多指令的取值,如“用户名内容”等,被定义为双引号字符串(quoted-string)。而实际上,”unq”注释则表示在生成字符串A1时,去掉其外部的引号。所以,当Authorization头域包含如下内容:
username="Mufasa", realm=myhost@testrealm.com
   并且用户 Mufasa 的密码为"Circle Of Life"时, H(A1) 可以表示为 H(Mufasa:myhost@testrealm.com:Circle Of Life),用于计算摘要的字符串不包含引号。
   注意,在摘要函数  H() 中的字符串里不允许出现空格,除非空格出现在双引号字符串的引号内或者请求实体内。例如,上面出现的字符串A1必须是:
Mufasa:myhost@testrealm.com:Circle Of Life
   在冒号的两边都不可以有空格,但是允许密码单词之间出现空格(Circle+SP+Of+SP+Life)。同样,其它由H()摘要的字符串也不能在用于分隔的冒号两边加空格,除非空格在引号内或被摘要的请求实体内。
   同样要注意的是,如果应用了完整性保护(integrity protection),即“qop=auth-int”,则 H(请求实体) 是请求实体(entity-body)的哈希值,而不是消息实体(message-body)的哈希值,该值在发送方进行任何传输编码前计算,之后,被接收方移除。
   要注意的是多部分实体(multipart)中的分隔符(boundaries)和嵌入的头信息都属于请求实体的一部分。
   (5)其他方面的考虑
   上述“请求方法”的值为定义在[2]的5.1.1小节的HTTP请求方法。“请求uri”的值为HTTP请求行中的URI,定义在[2]的5.1.2小节。“请求uri”的值可以是“*”、绝对URL或者绝对路径,在[2]的5.1.2小节有具体描述。虽然可能有多种不同的形式,但“请求uri”的值必须与当前请求行中出现的URI相同。比如,请求行中出现的是绝对URL,则“请求uri”的值必须也为绝对URL。“客户端随机值”是一个可选的,由客户端给出的值,用来防止选择明文攻击。
   认证服务器必须确保“请求uri”指令指定的资源与请求行中指定要访问的资源相同,如两者不同,服务器应该返回“400 Bad Request”错误。(因为该现象可能是遭受攻击的征兆,服务器实现者可以考虑将其记录在错误日志中。)之所以要把请求行中的URL在“请求uri”指令中重复一遍,是因为某些代理服务器实现可能会改变客户端的原始请求行。这种改变后(但在语义上可认为与原始请求行等效)的请求行可能导致服务器计算出的摘要与客户端计算出的不同。
   实现者应该注意认证事务如何与共享缓存进行交互。HTTP/1.1协议的规范为,当共享缓存(参见[2]的13.7小节)收到一个带“Authorization”头的请求及其响应时,它必须不能把该响应做为任何其他请求的回应,除非该响应中包含以下两种“Cache-Control”(缓存控制,见[2]的14.9小节)指令之一:其一,如果原始响应中包含“must-revalidate”(必须重新验证)缓存控制指令,则缓存可以使用该响应的实体去回复后来的请求,但必须先通过原始服务器重新验证该请求。在重新验证时使用新请求的请求头来允许原始服务器去认证新的请求。其二,如果原始响应中包含“public”(公开)缓存控制指令,则该响应的实体可以用来回复任何后来的请求。
3.2.3“Authentication-Info”响应头
   “Authentication-Info”(认证信息)响应头被服务器用来在认证成功时传递一些相关信息,其形式如下所示:
       认证信息响应头 = "Authentication-Info" ":" 认证信息
       认证信息       = 1#(下一个随机值 | [消息保护质量]
                  | [响应认证] | [客户端随机值]
                  | [随机值计数] )
       下一个随机值   = "nextnonce" "=" 随机内容
       响应认证       = "rspauth" "=" 响应摘要
       响应摘要       = <"> *小写HEX <">
       
   上述指令的意义及计算方法如下:
   (1)下一个随机值 
   “下一个随机值”指令的内容是服务器希望客户端在未来的认证响应中使用的随机值。服务器可通过发送带有“下一个随机值”的认证信息头,来实现一次性或以其他方式改变的随机值。如果“下一个随机值”不为空,则客户端应该在构建下一个请求的认证头时使用该随机值。如果客户端没有这么做,可能导致服务器以“stale=TRUE”(随机值过期)为响应要求重新认证。
   服务器实现应当小心处理采用这种机制而引发的潜在性能问题;如果每个请求都包含由服务器指定的、必须在下个请求中使用的“下一个随机值”,那么管道式(Pipelined)请求不可能实现。要想实现管道式请求,而且要顾及性能和安全性的平衡,可在一段有限时间内,允许使用旧的随机值。使用随机值计数可以在不危害管道的前提下,保留新服务器随机值的大多数安全特性。
   (2)消息保护质量
   指出服务器对该响应应用的“保护质量”选项。”auth”值表示认证;”auth-int”表示具有完整性保护的认证。服务器在此应该使用和客户端发来的对应请求中“消息保护质量”指令一致的值。
   (3)响应认证
   “响应认证”指令中可选的响应摘要用于支持客户端与服务器的互相认证——服务器用它来证明它知道用户的密钥,如果配合“qop=auth-int”指令,还可提供有限的响应完整性保护。“响应摘要”值的计算方法与认证头中的“请求摘要”基本一致,除了以下区别:
当“qop=auth”或未指定时,A2为
       A2 = ":" 摘要uri值
   当“qop=auth-int”时,A2为
       A2 = ":" 摘要uri值 ":" H(请求实体)
   其中,“摘要uri值”为该响应对应的请求里认证头中“uri”指令的值。“客户端随机内容”和“计数值”必须采用客户端请求中的值,因为该消息是对这些值的响应。如果指定了“qop=auth”或“qop=auth-int”,则“响应认证”、“客户端随机值”和“随机值计数”指令必须出现。
   
   在HTTP消息采用“chunked”传输编码时,“Authentication-Info”(认证信息)响应头允许出现在消息的尾部。
3.3摘要操作
   收到认证头后,服务器会通过检查用户名和密码是否正确来验证该认证头是否有效。为了实现这一点,服务器必须执行和客户端相同的摘要操作(如MD5),然后把结果与客户端给出的请求摘要进行比较。
   注意HTTP服务器并不需要知道用户的明文密码。只要该服务器知道H(A1)值,认证头的有效性就可以被验证。
   客户端响应了一个特定受保护区间的“WWW-Authenticate”质询,就是开始了一个该受保护区间的认证会话。该认证会话持续到客户端收到来自该受保护区间的任一服务器的另一个“WWW-Authenticate”质询为止。客户端应该记住分配给该会话的用户名、密码、随机值、随机值计数和不透明值,以便在该受保护区间内发起下一次请求时构造认证头。客户端在后续请求中应该先发制人的包含认证头,而不是等服务器发起“WWW-Authenticate”质询——这种机制可以提高服务器的效率,避免额外的认证质询往返。服务器可以选择接受旧的认证头信息,即使其中包含的随机值可能不是新的。或者,服务器也可以返回一个401响应,包含一个新的随机值,从而让客户端重试该请求——通过在响应中指定“stale=TRUE”,服务器可以告诉客户端只需要用新的随机值重试,不需要向用户询问新的用户名和密码。
   因为客户端在会话期间要把服务器提供的给它的“不透明值”返回给服务器,所以这一不透明数据可以用来传递认证会话的状态信息。(注意,任何这样的用法其实也可以通过在随机值中包含状态来实现,并且这样更加简便和安全。)例如,想要让一个服务器负责为保存在另一个服务器上的内容进行认证,可以这样实现:该服务器首先返回一个401响应,包含一个含有第二个服务器URI的“域”指令,以及一个含有状态信息的“不透明值”。客户端将重试该请求,此时,该服务器返回一个301或302重定向,指向第二个服务器的URI。此时,客户端会跟随重定向来到第二个服务器,并发送包含第一个服务器指定的“不透明值”的认证头。
   和基本认证方案一样,代理服务器也必须完整的传输摘要认证方案的头信息。这意味着,代理必须原封不动的转发“WWW-Authenticate”、“Authentication-Info”和“Authorization”头信息。如果代理想要在转发请求前对客户端进行认证,它可以使用3.6小节中定义的Proxy-Authorization头。
3.4安全协议协商
   对服务器来说,了解客户端有能力处理哪些安全方案是很有用的。
   可能存在这种情况,服务器直接要求使用摘要认证做为其认证方法,而不知道客户端是否支持它。如果客户端无法处理服务器指定的单一认证方案,客户端被鼓励优雅地失败。
3.5例子
   下面的例子假定通过GET请求来获取服务器上一个带有访问保护的文档。文档的URI是"http://www.nowhere.org/dir/index.html",客户端和服务器都知道该文档的用户名是"Mufasa",口令是"Circle Of Life"(三个单词间用一个空格分隔)。
   客户端在第一次请求该文档时,没有发送认证报头,于是服务器回应:
       HTTP/1.1 401 Unauthorized WWW-Authenticate: Digest
            realm="testrealm@host.com",
            qop="auth,auth-int",
            nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
            opaque="5ccc069c403ebaf9f0171e9517f40e41"
   客户端接下来会向用户询问用户名和密码,然后它会发送一个新请求,包含如下认证头:
       Authorization: Digest username="Mufasa",
            realm="testrealm@host.com",
            nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
            uri="/dir/index.html",
            qop=auth,
            nc=00000001,
            cnonce="0a4f113b",
            response="6629fae49393a05397450978507c4ef1",
            opaque="5ccc069c403ebaf9f0171e9517f40e41"
3.6“Proxy-Authenticate”和“Proxy-Authorization”头
   摘要认证方案也可以通过“Proxy-Authenticate”和“Proxy-Authorization”头信息,用于用户到代理,代理到代理,以及代理到原始服务器之间的认证。“Proxy-Authenticate”和“Proxy-Authorization”头的定义和行为在[2]的10.33和10.34小节有详细的说明。代理认证的处理方法和之前描述的客户端认证很相似。当收到需要认证的请求时,代理或服务器发出“407 Proxy Authentication Required”响应,包含一个“Proxy-Authenticate”头。摘要质询使用的“Proxy-Authenticate”头与3.2.1小节定义的“WWW-Authenticate”头一致。
   然后客户端或代理必须重新发送包含“Proxy-Authorization”头的请求,“Proxy-Authorization”头中的指令与3.2.2小节定义的“Authorization”头一致。
   对后续响应,服务器发送“Proxy-Authentication-Info”头,其中的指令与“Authentication-Info”头一致。
   注意从原理上来说,客户端可能同时被代理和最终服务器要求认证,但两者绝对不会出现在同一个响应中。

参 考 文 献
[1] Berners-Lee, T., Fielding, R. and H. Frystyk, "Hypertext Transfer Protocol -- HTTP/1.0", RFC 1945, May 1996.
[2] Fielding, R., Gettys, J., Mogul, J., Frysyk, H., Masinter, L., Leach, P. and T. Berners-Lee, "Hypertext Transfer Protocol - HTTP/1.1", RFC 2616, June 1999.
[3] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, April 1992.
[4] Freed, N. and N. Borenstein. "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies", RFC 2045, November 1996.
[5] Dierks, T. and C. Allen "The TLS Protocol, Version 1.0", RFC 2246, January 1999.
[6] Franks, J., Hallam-Baker, P., Hostetler, J., Leach, P., Luotonen, A., Sink, E. and L. Stewart, "An Extension to HTTP: Digest Access Authentication", RFC 2069, January 1997.
[7] Berners Lee, T, Fielding, R. and L. Masinter, "Uniform Resource Identifiers (URI): Generic Syntax", RFC 2396, August 1998.
[8] Kaliski, B.,Robshaw, M., "Message Authentication with MD5", CryptoBytes, Sping 1995, RSA Inc, (http://www.rsa.com/rsalabs/pubs/cryptobytes/spring95/md5.htm).
[9] Klensin, J., Catoe, R. and P. Krumviede, "IMAP/POP AUTHorize Extension for Simple Challenge/Response", RFC 2195, September 1997.
[10] Morgan, B., Alvestrand, H., Hodges, J., Wahl, M., "Authentication Methods for LDAP", Work in Progress.
回复列表(0|隐藏机器人聊天)
帖子没有回复
添加新回复
该帖子已关闭评论,仅楼主可回复。