摘要

出于安全考虑,HTTP规范定义了几种认证方式以对访问者身份进行鉴权,最常见的认证方式之一是Digest认证

Digest认证简介

        HTTP通讯采用人类可阅读的文本格式进行数据通讯,其内容非常容易被解读。出于安全考虑,HTTP规范定义了几种认证方式以对访问者身份进行鉴权,最常见的认证方式之一是Digest认证。Digest是一种加密认证方式,通讯中不会传输密码信息,而仅采用校验方式对接入的请求进行验证。

        Digest认证支持的加密算法有:SHA256,SHA512/256,MD5。上述这几种算法都是由哈希函数来生成散列值,其加密过程为单向计算,请求方无法反算出密码明文。这里需要强调的是,HTTP认证像其它认证方式一样仅仅对者资源访问进行鉴权,但无法保证通讯过程的安全。

通讯协商过程

HTTP通讯安全中的Digest摘要认证释义与实现_服务器

发起请求

# <<127.0.0.1:50315
GET / HTTP/1.1
Host: 127.0.0.1:9090

质询

# >>127.0.0.1:50315
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Digest realm="http-auth@mozicoder.org",
              nonce="M0P1F4D75VG1IFAJNKA7YG5FW1WRMGCP",
              opaque="IGH008EZM3E277G3BXVGWTABKRE6URHK",
              algorithm=MD5,
              qop="auth"
Server: Mozi.HttpEmbedded/1.4.7.0
 

请求验证

# >>127.0.0.1:50325
GET / HTTP/1.1
Host: 127.0.0.1:9090
Authorization: Digest realm="http-auth@mozicoder.org",
            username="admin",
            nonce="M0P1F4D75VG1IFAJNKA7YG5FW1WRMGCP",
            uri="/", 
            algorithm=MD5,
            response="1cfe3a00105362cbe5174cb525784f4f",
            opaque="IGH008EZM3E277G3BXVGWTABKRE6URHK",
            qop=auth,
            nc=00000001, 
            cnonce="0698175c27a8bcee"

校验并返回

# >>127.0.0.1:50325
HTTP/1.1 200 OK
Server: Mozi.HttpEmbedded/1.4.7.0

Digest认证的参数

服务端

realm

认证域。明文信息,用于提示客户端使用哪些用户名和密码。这个值可以设置成任意字符串,建议不要超出ASCII范畴。建议设置成 {string}@{domain} 这种格式,例如:http-auth@mozicoder.org。

domain

受保护的域名信息。以空格为分割,可以是绝对地址,也可以是相对路径。

nonce

随机数。用于参与加密运算,其值取决于服务端如何生成这个参数值。推荐使用B64字符串或HEX字符串。服务端可通过算法实现none的有效时间来防止重放攻击。

opaque

透传字符串。客户端在请求中附带同样的参数值。

stale

随机数是否过期。用于指示客户端认证信息中的随机数是否过期。

algorithm

算法类型。算法类型包括SHA256,SHA512/256,MD5。如果参数列表中没有出现这个值,则默认使用MD5。建议使用MD5。

qop

加密质量。可选值为auth,auth-int。具体区别请文章中的算法实现。

charset

字符集。其唯一可以设置的值为"UTF-8"。一般不设置这个值,这个参数意义不大。

userhash

是否将用户名也进行加密。取值范围:true|false,默认不进行设置,也就是false。

客户端

realm

认证域。明文信息,用于提示客户端使用哪些用户名和密码。使用服务端返回的字符串。

response

加密结果。此值是加密检验的最终对比对象。

username

用户名。

username*

扩展的用户名。当用户名中出现了不符合ABNF范式的字符串的时候,使用这个参数设置用户名和密码,同时也要满足userhash=false这个条件。

uri

路径信息。指示当前正在请求的路径信息,值为相对于根路径的相对路径。

qop

加密质量。可选值为auth,auth-int。具体区别请文章中的算法实现。

cnonce

客户端随机数。用于参与加密运算,其值取决于客户端如何生成这个参数值。推荐使用B64字符串或HEX字符串。服务端可通过算法实现none的有效时间来防止重放攻击。

nc

客户端请求校验的次数。是一个16进制的数值,表示同一nonce下客户端发送出请求的数量。

userhash

是否将用户名也进行加密。取值范围:true|false,默认不进行设置,也就是false。注意:上述参数值仅username, realm, nonce, uri,response, cnonce, and opaque这几个字段可以使用""进行包裹。

Digest认证的验证算法

response=H(HA1:HD:HA2)

//如果加密算法以"-sess"结束

if  !algorithm.EndWith("-sess")

{

        HA1=H(username:realm:password)

}else{

        HA1=H(username:realm:password: nonce:cnonce)

}

HD=nonce:nc:cnonce:qop

if  qop!="auth-int"

{

        HA2=H(Method:url)

}else{

        HA2=H(Method:url:Body-Length)

}

参考文档

[RFC7616]    R. Shekh-Yusef, Ed.D. Ahrens,S. Bremer,"HTTP Digest Access Authentication"