HTTP认证

 

一、前言

        HTTP认证是Web服务器对客户端的权限进行认证的一种方式,能够为Web应用提供一定程度的安全保障。目前一些Web应用项目已经提出了采用HTTP 认证的需求。一般的Web容器都提供基本认证和摘要认证的API。RFC2617对此有详细的描述。

 

二、HTTP认证机制

        HTTP认证采用“质询-响应(challenge-response)”的机制。“质询”是服务器端对客户端的质询,即要求客户端发送认证信息;“响应”是客户端对“质询”的响应,即发送带有认证信息的HTTP请求。
        一般来说,客户端第一次请求一个URI时,并不知道是否需要认证,因此总是不带认证信息的,这时服务器端就会找不到认证信息,认证失败,于是向客户端发出一个“质询”。
        所谓“发出质询”,就是给客户端发送一个HTTP响应,其状态码为401 (Unauthorized),并且包含消息头WWW-Authenticate,客户端看到这个响应就知道这个URI需要认证。WWW-Authenticate消息头格式为
        WWW-Authenticate:challenge
        其中<challenge>是就是质询信息,RFC2617中的定义为:
challenge   = auth-scheme 1*SP 1#auth-param
auth-scheme = token
auth-param  = token "=" ( token | quoted-string )
        在challenge的定义中,首先是auth-scheme,即认证方案,它被定义为一个token,即预定义的符号。所谓token,就是一些字符 串,但这些字符串不是随意的,而是大家约定的,它们具有特定的含义。auth-scheme的取值只能是Basic或Digest,分别表示基本认证和摘 要认证,这两个单词就是token。这里没有把auth-scheme定义为Basic|Digest,而是一个token,说明还可以进行扩展,还可以 取其他符号——只要服务器端和客户端互相约定都能理解就行。
        接着,“1*SP”表示1个或多个空格符。其中“1*”表示数量为1个到多个,“SP”即空格符(ASCII码32)。
        然后是“1#auth-param”,表示一个auth-param的列表。其中的“1#”也表示后面的元素是1到多个,但与“1*”不同的是,“1#” 表示一个“列表”,即元素之间是用逗号“,”分隔开的。列表中的每个auth-param被定义为一个名值对,即
        符号=符号
        或
        符号=“引号中的字符串”
        这两种形式。
        基本认证和摘要认证中都定义了一个相同的auth-param,即realm,定义为:
    realm       = “realm”“=” realm-value
    realm-value = quoted-string
realm- value是一个两端加引号的大小写相关的字符串,表示要求认证的“领域(realm)”。领域是由服务器自己决定的,不同的服务器可以设置自己的领域, 同一个服务器也可以有多个领域。质询中包含领域信息是为了让客户端知道哪个范围的用户名是合法的,RFC2617中建议领域至少包含主机名和有权限的用户 组,例如“[email protected]”。
        客户端收到质询后,应该给服务器端返回一个“响应”,即重新发送一个新的HTTP请求。这个新的HTTP请求与前一个HTTP请求的差别在于多了一个 Authorization消息头,该消息头的格式为Authorization:credentials,其中的credentials就是认证信息, 认证信息的格式根据不同的认证方案而有所不同。
        服务器端对认证信息进行判断,只有认证通过,才会响应客户端的请求。


      1. 基本认证
        基本认证的质询中只定义了一种auth-param,即realm,因此基本认证的质询也定义为
challenge = “Basic” realm
质询举例:
        当服务器端认证不通过,将返回一个状态码为401(Unautherized)的响应消息,并带有如下消息头:
       WWW-Authenticate: Basic realm=“My Secret World”
        基本认证的认证信息credentials定义为:
    credentials       = “Basic” basic-credentials
    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            = *
    password          = *TEXT
        简单说,认证信息就是“Basic”后面加上“<用户名>:<密码>”的Base64编码,只不过这里的Base64编码不对每一行的字符数做最大76个的限制。
        认证信息举例:
        如果用户名为“abc”,密码为“abcd”,将“abc:abcd”进行Base64编码得到“YWJjOmFiY2Q=”,于是消息头中认证信息为
Authorization: Basic YWJjOmFiY2Q=


       2. 摘要认证
        由于基本认证被认为是不安全的认证方式,摘要认证作为替代方案被制定了出来。摘要认证中,用户名和密码不会以明文方式传送,而是经过了加密。从名称可以看 出,是生成了信息摘要,客户端和服务器使用各自的密码以同样的算法生成信息摘要,两者比较即可判断客户端的密码是否正确。
        摘要认证仍然采用WWW-Authenticate和Authorization两个消息头,另外还规定了消息头Authentication- Info。消息头Authentication-Info用于认证通过之后,服务器给客户端返回一些信息,例如可以用来指定下一次认证用的临时值,或者也 生成一个摘要,表明服务器确实知道用户密码,等等。不过这个消息头并不是必须的,实际应用中一般也用不着,因此Web平台中目前没有实现,这里也不做介 绍,若有兴趣请查看RFC2617。

 

三、HTTP认证的安全性

       1. 基本认证的安全性
        基本认证不是一种安全的认证方式,因为Base64编码仅仅是编码,而不是加密,以这种形式在互联网上传递用户名和密码,其危险性是显而易见的。但如果对安全性要求不高,则可以使用这种认证方式做为最简单的安全措施--毕竟比没有安全措施要好。
        当然,如果能够保证中间不会有人截取数据包,例如处于内部局域网,或者底层协议是安全的(如使用SSL或其他一些安全机制),倒是可以弥补HTTP基本认证在安全性方面的不足。
       2. 摘要认证的安全性
        由于基本认证过于危险,人们才使用摘要认证作为一种替代方案。但它也仅仅是作为基本认证的替代品,因为它本身也不是十分安全的,也存在一些弱点。
        (1)摘要认证只能作为权限认证机制,并非保密措施,因为消息体并没有被加密。qop使用“auth-int”只能保证消息体不被修改,不能防止被偷看。
        (2)Replay攻击:攻击者可能截取一次摘要信息,然后利用相同的摘要信息请求相同的URI,如果该URI可以通过POST或PUT方法访问,则攻击 者可能修改消息体。控制nonce中的时间戳和nc次数有助于减小replay攻击机会;每次使用新的nonce值(用Authentication- Info消息头)可避免遭受replay攻击,当然也增加了开销。
        (3)MITM(Man in the Middle)攻击:攻击者截取网络数据包,给客户端发送一个假的质询,只要求客户端使用基本认证,从而取得密码。MITM最常见的方式是提供一个“免 费”的但其实是恶意的代理服务器。要防止此类攻击,可双方约定只使用摘要认证,不允许使用基本认证,但一般浏览器并不支持指定认证方式,除非是自己开发的 客户端。
        其他还有些攻击方式,例如通过“查字典”猜密码等比较野蛮的方式。虽然摘要认证有这些弱点,但在许多情况下还是有它的使用价值的,至少比基本认证是好多了。

你可能感兴趣的:(加密,服务器,basic,token,authorization,credentials)