如何获得正确的摘要身份验证

Posted

技术标签:

【中文标题】如何获得正确的摘要身份验证【英文标题】:How to get Digest authentication right 【发布时间】:2014-09-08 21:59:02 【问题描述】:

我尝试编写一个 C++ 应用程序,但我必须进行 HTTP Digest 身份验证。问题主要不在于 C++,而在于没有建立连接这一事实。我尝试访问的网站如下:httpbin.org/digest-auth/auth/user/passwd。

考虑以下服务器对简单 GET /digest-auth/auth/user/passwd 的响应:

HTTP/1.1 401 UNAUTHORIZED Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: * Content-Type: text/html; charset=utf-8 Date: Mon, 08 Sep 2014 15:10:09 GMT Server: gunicorn/18.0 Set-Cookie: fake=fake_value Www-Authenticate: Digest realm="me@kennethreitz.com", nonce="2a932bfb1f9a748a7b5ee590d0cf99e0", qop=auth, opaque="2d09668631b42bff8375523e7b27e45e" Content-Length: 0 Connection: keep-alive

A1 然后计算为user:me@kennethreitz.com:passwd 并散列为4de666b60f91e2444f549243bed5fa4b,我将其称为HA1。 A2 被计算为 GET:/digest-auth/auth/user/passwd 并散列为 b44272ea65ee4af7fb26c5dba58f6863,我将其称为 HA2。

有了这些信息,响应计算为HA1:nonce:1:ac3yyj:auth:HA2,其中HA1HA2 是我们刚刚计算的值,随机数取自上面的服务器响应,总共是:4de666b60f91e2444f549243bed5fa4b:2a932bfb1f9a748a7b5ee590d0cf99e0:1:ac3yyj:auth:b44272ea65ee4af7fb26c5dba58f6863。它的哈希是55f292e183ead0810528bb2a13b98e00

结合所有这些信息应该足以使用摘要身份验证建立 http 连接。但是,服务器拒绝了以下请求,并以另一个 HTTP/1.1 401 回答。

GET /digest-auth/auth/user/passwd HTTP/1.1 Host: httpbin.org Authorization: Digest username="user", realm="me@kennethreitz.com",nonce="2a932bfb1f9a748a7b5ee590d0cf99e0",uri="/digest-auth/auth/user/passwd",qop=auth,nc=1,cnonce="ac3yyj",response="55f292e183ead0810528bb2a13b98e00",opaque="2d09668631b42bff8375523e7b27e45e"

请注意,格式不显示请求的结构。从 Authorization 到 opaque 的块其实就是一行。

请随意重新进行 md5 计算 - 但我已经手动重新计算并获得了与我的程序相同的哈希值。我使用该工具 (http://md5-hash-online.waraxe.us/) 进行手动计算。

我是否在这里遗漏了一些明显的东西,可能在某种程度上误解了标准?为什么我无法获得授权?

【问题讨论】:

RFC 给出了一个应该如何工作的例子。你得到同样的答案吗? @AlanStokes:您好,这是个好建议!我用 RFC 示例中提供的数据为我的程序提供了数据,我得到了与 RFC 相同的 response 哈希值。当它连接到 httpbin.org 时,我也嗅探了 firefox 并且 - 在我看来 - 请求是相等的(看看这里:pastebin.com/UkpP1shP )......我现在真的没有想法了。 @AlanStokes:有趣 - 看起来 curl 也有同样的问题:试试curl -v --digest -u user:passwd http://httpbin.org/digest-auth/user/passwd 正确的命令是:curl -v --digest -u user:passwd http://httpbin.org/digest-auth/auth/user/passwd 而 lwp-request (lwp-request -USse -C user:passwd http://httpbin.org/digest-auth/auth/user/passwd) 也失败了。我认为服务器可能配置错误-但是为什么firefox和wget可以成功授权? 【参考方案1】:

终于明白了。身份验证本身是完全正确的。

服务器要求设置 cookie。显然,也必须在响应中显示该 cookie。这就解释了为什么 firefox(作为浏览器)可以正确地进行身份验证,而 curl 和 lwp-request 却不能遵守标准——RFC 对 cookie 只字未提。为什么我们有没人关心的标准?

无论如何,将Cookie: fake=fake_value 附加到标头即可解决问题。

【讨论】:

以上是关于如何获得正确的摘要身份验证的主要内容,如果未能解决你的问题,请参考以下文章

如何覆盖 Apache 的摘要身份验证

.Net Core HttpClient 摘要式身份验证

使用 jQuery 可以进行摘要身份验证吗?

您如何将 JMeter 与摘要式身份验证一起使用?

HTTPS 和摘要式身份验证

使用 PHP POST 到 Web 服务的摘要式身份验证的客户端部分