现在的位置: 首页 > 综合 > 正文

HTTP的无鉴权_基本鉴权和摘要鉴权

2013年08月05日 ⁄ 综合 ⁄ 共 7019字 ⁄ 字号 评论关闭

一 无鉴权方式

就是正确的客户端请求发到服务器后,HTTP服务器返回200状态码并且把内容直接返回。

报文示例:

请求:

GET.http://10.127.194.3:8061/VoiceObjects.....

返回:

HTTP/1.1.200.OK..Date:.Fri,.28.Oct.20.....

 

二 基本鉴权方式

基本鉴权和摘要鉴权方式都是基于一种叫challenge-response鉴权模式(challenge-response authentication mechanism)来运作的。这里先解释一下这种鉴权模式,它是这么一种请求-响应顺序:

A  Client发送“无鉴权”请求给Server

B  Server给Client返回401(Unauthorized),并附上Server需要的鉴权方式(基本鉴权或摘要鉴权),和realm(下面会解释),和其他信息给Client。

C  Client基于Server给回的信息重新组织请求消息,带上鉴权信息再次发送请求。

 

基本鉴权和摘要鉴权都是基于上面的模式运作的,但到实际应用中,也不一定全按照上面的顺序操作,比如如果双方早就约定好要用某种鉴权方式,就可以省略去A和B的步骤一步到位。

 

Realm:这个在基本鉴权和摘要鉴权里面都会附上,这是服务器指定的鉴权分类标志(不知道如何用中文更好地表达了,原文:These realms allow the protected resources on a server to bepartitioned into a set of protection spaces, each with its own authenticationscheme and/or authorization database.),就是说Client访问不同的链接,有可能会接收到不同的Realm标志,从而根据接受到的不同Realm值,用不同的用户名和密码或其他鉴权信息来组织下一个请求。

 

基本鉴权要求:

当Server要求基本鉴权的时候,它必须在返回的401消息中带上“WWW-Authenticate”头域,后接一个“Basic”关键字,再后面接一个realm和realm值,中间用空格分开:

      challenge   = "Basic" realm

      realm       = "realm" "="realm-value

      realm-value = quoted-string

Client收到消息的时候,要带上“Authorization”头域,后接一个“Basic”关键字,再后面接用“:”号相连的用户名和密码的base64加密字符串:

      credentials = "Basic"basic-credentials

      basic-credentials = base64-user-pass

      base64-user-pass  = <base64 [4] encoding of user-pass,except not limited to 76 char/line>

      user-pass   = userid ":" password

      userid      = *<TEXT excluding ":">

      password    = *TEXT

报文示例:

请求尝试:

GET.http://10.127.194.3:8061/VoiceObjects/...

请求尝试回复:

HTTP/1.1.401.Unauthorized..Date:.Thu,.20.Oct.2011.15:16:22.GMT..Server:.Jetty/5.1.4.(SunOS/5.10.sparc.java/1.5.0_15..WWW-Authenticate:.basic.realm="VORealm"..Content-Type:.text/html..Content-Length:.1249.......

再次请求:

GET.http://10.127.194.3:8061/VoiceObjects/sfdsdf.HTTP/1.1..Authorization:.Basic.c2ljYXA6c2ljYXAxMjM=..Connection:.Keep-Alive..Host:.10.127.194.3:8061..Content-Length:.0....

再次请求回复:

HTTP/1.1.200.OK..Date:.Thu,.20.Oct.2011.15:12:36.GMT..Server:.

 

三 摘要鉴权方式:

上面已经说了摘要鉴权方式类似于请求鉴权方式,只不过摘要鉴权方式有更复杂的计算方式。

开始之前,解释一下下面要用到的表达方式:

H(data) =MD5(data)

----这个表示把data用MD5算法加密。

KD(secret, data)= H(concat(secret, ":", data))

----这个表示把secret和data用”:”号相连接后,再用MD5算法加密。

----secret和data都是某字符串。

 

如果Server回复401,则在摘要鉴权下,应该带下面这些额外信息:

      challenge        = "Digest" digest-challenge

 

      digest-challenge  = 1#( realm | [ domain ] | nonce |

                          [ opaque ] |[ stale ]| [ algorithm ] |

                          [ qop-options ] |[auth-param] )

 

      domain            = "domain" "="<"> URI ( 1*SP URI ) <">

      URI               = absoluteURI | abs_path

      nonce             = "nonce" "="nonce-value

      nonce-value       = quoted-string

      opaque            = "opaque" "="quoted-string

      stale             = "stale" "="( "true" | "false" )

      algorithm         = "algorithm" "="( "MD5" | "MD5-sess" |

                           token )

      qop-options       = "qop" "="<"> 1#qop-value <">

      qop-value         = "auth" |"auth-int" | token

下面一一解释一下每个值的含义:

A  realm: 跟摘要鉴权意义差不多,不再赘述。

B  domain: 是双引号引住的一个URI地址列表,每个URI之间用空格分开,比如”http://www.baidu.com /value/index.html”,就表示了两个地址,一个是http://www.baidu.com,一个是/value/index.html。domain的意义是标志此次返回的401里带上的信息可以用在哪些URI里面去?

C  nonce: 这个是摘要鉴权中非常重要的值,它是一串由Server生成的base64加密或16进制的字符串(this string be base64 or hexadecimal data),在摘要鉴权流程中,每次Server产生401,就要返回一个不同的nonce值。标准推荐了一个算法:time-stampH(time-stamp ":" ETag ":" private-key),time-stamp是Server产生nonce时的时间挫;ETag是HTTP解决缓存机制的方式,通常也是一个奇怪的串,但可以用来标示被请求的文件的版本;private-key是只有Server才知道的私有Key。一般情况下,每个HTTP服务器都是有配置能自动生成nonce值的而不用我们写代码。Client一定要使用这个值进行请求内容的计算,下面会介绍。

额外说一下,我们看nonce值里面会有时间挫,这个时间也会被Server用来判断这个nonce是什么时候生成的,到现在还有没有过期?Client会在请求信息中带上这个值,发到Server端,Server端拿到这个nonce值,解码或者不解码,反正Server产生的,Server就知道如何处理这个nonce,并用它带的信息来判断这个请求是否有效。

D  opaque: 一串由Server指定的字符串,Client在相同的保护空间(protection space,就是一堆使用相同用户名和密码的链接)内发送的请求,就把opaque原封不动地返回给Server就可以了。

E  stale: 用来指示Client的前一个请求里的nonce是否过期了。

TRUE:

表示用户名和密码是正确的,但nonce过期了。

FALSE:

表示nonce是正确的,但用户名和密码不正确,这时候,Client要换一个用户名和密码重新发送请求(对IE来说,就是弹出输入用户名和密码的对话框)。

F  algorithm:  Server和Client算法约定,一般是MD5或"MD5-sess"。

G  qop-options:  可选的,一般是"auth"或"auth-int"。祥见Client的算法部分。

H  auth-param:  未来扩展使用。

 

当Client接受到上面的信息后,就要再次准备请求消息,摘要鉴权的请求消息如下:

       credentials      = "Digest" digest-response

       digest-response  = 1#( username | realm | nonce | digest-uri

                       | response | [ algorithm] | [cnonce] |

                       [opaque] | [message-qop]|

                           [nonce-count]  | [auth-param] )

 

       username         = "username" "="username-value

       username-value   = quoted-string

       digest-uri       = "uri" "="digest-uri-value

       digest-uri-value = request-uri   ; As specified by HTTP/1.1

       message-qop      = "qop" "=" qop-value

       cnonce           = "cnonce" "="cnonce-value

       cnonce-value     = nonce-value

       nonce-count      = "nc" "=" nc-value

       nc-value         = 8LHEX

       response         = "response" "="request-digest

       request-digest = <"> 32LHEX<">

       LHEX             = "0" | "1" | "2" | "3" |

                           "4" |"5" | "6" | "7" |

                           "8" |"9" | "a" | "b" |

                           "c" |"d" | "e" | "f"

A  username:  跟某个realm相关联的用户名;

B  digest-uri:  就是HTTP头里的请求URI,拷贝一份到这里就可以了。拷贝的目的是可能会经过Proxy,把原始URI修改了。


 

C  qop:  Server给过来的值,如果Server指定了几个,那客户端就一定要选一个。这个字段的作用是指定了算response字符的算法。

D  cnonce:如果Server指定了qop,那请求信息里一定要有这个值。如果Server没有指定qop,那一定不能带上这个值。这个值是由Client用自己的方式指定的一串字符串。

E  nonce-count:  如果Server指定了qop,那请求信息里一定要有这个值。如果Server没有指定qop,那一定不能带上这个值。使用nonce的次数,包括此次。是二进制表示的次数。

F  response:  这个是最重要的请求信息,它的计算方法如下:

   如果"qop"值是"auth"或"auth-int":

      request-digest  = <"> < KD ( H(A1),     unq(nonce-value)

                                         ":" nc-value

                                          ":" unq(cnonce-value)

                                         ":" unq(qop-value)

                                         ":" H(A2)

                                  )<">

   如果未指定qop值:

      request-digest  =

                 <"> < KD ( H(A1),unq(nonce-value) ":" H(A2) ) ><">

关于A1和A2,计算方法如下:

A1:

如果"algorithm"是MD5,那么

A1       = unq(username-value) ":"unq(realm-value) ":" passwd

如果"algorithm"是MD5-sess,那么A1只会在受到401后的所有请求的第一次请求中计算一次,计算方法如下:

A1       = H( unq(username-value) ":"unq(realm-value)

                     ":" passwd )

                     ":"unq(nonce-value) ":" unq(cnonce-value)

 

A2:

如果qop的值是"auth"或者未指定,则:

A2       = Method ":" digest-uri-value

如果qop的值是"auth-int",则:

A2       = Method ":" digest-uri-value":" H(entity-body)

Method是HTTP的请求方法,比如“Get”“POST”等,可以看HTTP协议文档的5.1.1章节;digest-uri-value =request-uri   ; As specified by HTTP/1.1;entity-body在HTTP协议文档的7.2章节。

 

报文示例:

第一次:

GET.http://10.119.244.39:8099/VoiceObjects...

第二次:

HTTP/1.1.401.Unauthorized..Date:.Wed,.08.Dec.2010.17:16:17.GMT..Server:.Jetty/5.1.4.(SunOS/5.10.sparc.java/1.5.0_15..WWW-Authenticate:.Digest.realm="VORealm",.domain="/VoiceObjects",.nonce="csP7xiwBAAB4QgAH08FxchbbLhA1zeCy",.algorithm=MD5,.qop="auth"..Content-Type:.text/html..Content-Length:.1249...........

第三次:

GET.http://10.119.244.39:8099/VoiceObjects/sdfsdfg.HTTP/1.1..Authorization:.Digest.username="ggggg",.realm="VORealm",.nonce="csP7xiwBAAB4QgAH08FxchbbLhA1zeCy",.uri="/VoiceObjects/DialogMappingAUTH",.response="2d2caa1d1043150281b61e92322a26d8",.algorithm=MD5,.qop=auth,.nc=00000001,.cnonce="01343c114a9c5e842351ce3eaedc1ed1"..Connection:.Keep-Alive..Host:.10.119.244.39:8099..Content-Length:.0....

第四次:

HTTP/1.1.200.OK..Date:.Thu,.20.Oct.2011.15:12:36.GMT..Server:...

【上篇】
【下篇】

抱歉!评论已关闭.