使用 net-http-digest_auth 的未知算法 MD5

Posted

技术标签:

【中文标题】使用 net-http-digest_auth 的未知算法 MD5【英文标题】:Unknown algorithm MD5 using net-http-digest_auth 【发布时间】:2012-05-26 23:17:42 【问题描述】:

我正在尝试对服务器进行一些摘要授权,然后使用 nokogiri 解析生成的 html。我正在使用 net-http-digest_auth gem (https://github.com/drbrain/net-http-digest_auth) 来进行 url 连接。一切都很好,直到我启动了 digest_auth 代码(第 20 行);它会引发“未知算法“MD5”错误”..

来自控制台的完整错误消息: ~/.rvm/gems/ruby-1.9.3-p194@rails32/gems/net-http-digest_auth-1.2.1/lib/net/http/digest_auth.rb:105:in 'auth_header': unknown algorithm ""MD5"" (Net::HTTP::DigestAuth::Error) from ./server_connection.rb:20:in '<main>'

第 20 行是授权行: auth = digest_auth.auth_header uri, res['www-authenticate'], 'GET'

这是我的完整代码(几乎完全是来自 github 链接中使用的示例代码的逐字记录):

#!/usr/bin/env ruby
require 'uri'
require 'net/http'
require 'net/http/digest_auth'

digest_auth = Net::HTTP::DigestAuth.new

uri = URI.parse 'http://url/controlpage?name=_internal_variables_&asList=1&useJS=True'
uri.user = 'username'
uri.password = 'password'

h = Net::HTTP.new uri.host, uri.port

req = Net::HTTP::Get.new uri.request_uri

res = h.request req

# res is a 401 response with a WWW-Authenticate header
auth = digest_auth.auth_header uri, res['www-authenticate'], 'GET'

# create a new request with the Authorization header
req = Net::HTTP::Get.new uri.request_uri
req.add_field 'Authorization', auth

# re-issue request with Authorization
res = h.request req

if res.code == "200"
  page = Nokogiri::HTML(res)
  isDaylight = page.css('.controlTitle:contains("isDaylight") ~ .controlValue');
  puts isDaylight.content
end

通过 Chrome 的开发工具更新了这个问题以包含请求标头:

GET /_getupdatedcontrols?name=_internal_variables_&asList=True&folderFilter=0&changeCount=479&serverState=idle HTTP/1.1
Host: url
Connection: keep-alive
Cache-Control: no-cache
Authorization: Digest username="username", realm="Indigo Control Server", nonce="71079e9f29f7210325ae451d0f423f07", uri="/_getupdatedcontrols?name=_internal_variables_&asList=True&folderFilter=0&changeCount=479&serverState=idle", algorithm=MD5, response="bc056cc472d35f7967973cb51c5b1a65", qop=auth, nc=00005649, cnonce="18dfcf3e4a7b809d"
X-Indigo-Web-Server-Version: 1
X-Prototype-Version: 1.6.0.3
X-Requested-With: XMLHttpRequest
Pragma: no-cache
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.17 Safari/536.11
Accept: text/javascript, text/html, application/xml, text/xml, */*
Referer: http://url/controlpage?name=_internal_variables_&asList=1&useJS=True
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

【问题讨论】:

【参考方案1】:

我最终使用httpclient gem 来完成同样的事情。

完成我所追求的最终代码:

#!/usr/bin/env ruby
require 'httpclient'
require 'nokogiri'

c = HTTPClient.new
c.debug_dev = STDOUT

c.set_auth("http://domain.com", "username", "password")

doc = Nokogiri::HTML(c.get_content("http://domain.com"))
isDaylight = "";
doc.css('.controlTitle:contains("isDaylight") ~ .controlValue').each do |var|
  isDaylight = var.content
end

if (!isDaylight)
  system("curl -X PUT --digest -u username:password -d isOn=1 http://domain.com")
else
  system("curl -X PUT --digest -u username:password -d isOn=0 http://domain.com")
end

我希望这对可能正在使用家庭自动化服务器并需要轻松进行基于摘要的身份验证的其他人有所帮助。

【讨论】:

【参考方案2】:

赛斯, 我在使用 ruby​​ 编写脚本时遇到了同样的问题。我是 ruby​​ 的新手,但经过一些谷歌搜索和一些 Charles Proxy 向我展示了发生了什么,我发现 HTTP 实现在 Auth 标头的 algorithm="MD5" 部分中包含引号是很常见的,这是不正确的根据规范(应该是算法=MD5,不带引号)。您从 Chrome devtools 更新的标头日志显示您的服务器响应符合规范,但 ruby​​ 库在解释该响应字符串时不是。这可以通过

看到

您的服务器的 401 响应包括:

注意算法=MD5

Authorization: Digest username="username", realm="Indigo Control Server", nonce="71079e9f29f7210325ae451d0f423f07", uri="/_getupdatedcontrols?name=_internal_variables_&asList=True&folderFilter=0&changeCount=479&serverState=idle", algorithm=MD5, response="bc056cc472d35f7967973cb51c5b1a65", qop=auth, nc=00005649, cnonce="18dfcf3e4a7b809d"

但是使用这个 Ruby 库的初始请求的控制台输出显示:

注意算法=\"MD5\"

<- "GET /some/request HTTP/1.1\r\nAccept: */*\r\nUser-Agent: Ruby\r\nConnection: close\r\nHost: 10.1.0.15\r\n\r\n"
-> "HTTP/1.1 401 Unauthorized\r\n"
-> "Content-Length: 530\r\n"
-> "Server: SomeServer/5.0\r\n"
-> "Allow: GET, HEAD, POST, PUT\r\n"
-> "Date: Sun, 27 Jan 2013 00:29:23 GMT\r\n"
-> "Content-Type: text/html;charset=utf-8\r\n"
-> "Www-Authenticate: Digest realm=\"Some Realm\", nonce=\"5a8b8b46cfb84466431baf454eb9ddb9\", algorithm=\"MD5\", qop=\"auth\"\r\n"

对于原帖中的脚本示例,我将插入以下两行:

www_auth_response = res['www-authenticate']
www_auth_response["algorithm=\"MD5\""] = "algorithm=MD5"

并修改第三行:

auth = digest_auth.auth_header uri, www_auth_response, 'GET'

如下:

...

res = h.request req

# res is a 401 response with a WWW-Authenticate header
www_auth_response = res['www-authenticate']
www_auth_response["algorithm=\"MD5\""] = "algorithm=MD5"
auth = digest_auth.auth_header uri, www_auth_response, 'GET'

# create a new request with the Authorization header
req = Net::HTTP::Get.new uri.request_uri
req.add_field 'Authorization', auth

...

这里发生的重要事情是我们正在修改从您最初的未经授权的 401 请求返回的 www-authenticate 字符串(由这个 ruby​​ 库解释)。将修改后的标头字符串 (www_auth_response) 发送到 digest_auth.auth_header 方法不会产生错误。至少这在我的脚本中对我有用!

希望对你有帮助!

马特

【讨论】:

很好的回应马修!非常感谢您跟进我原来问题的确切原因。

以上是关于使用 net-http-digest_auth 的未知算法 MD5的主要内容,如果未能解决你的问题,请参考以下文章

使用“使用严格”作为“使用强”的备份

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

Sqlmap的使用

Kettle java脚本组件的使用说明(简单使用升级使用)

PageHelp的使用getParameter的使用zpage-nav的使用QRcode的使用wxpay微信支付的使用jackson-xml数据的转换

hbs使用手册