Неизвестный алгоритм MD5 с использованием net-http-digest_auth

Я пытаюсь выполнить дайджест авторизацию на сервере, а затем проанализировать полученный HTML с помощью nokogiri. Я использую гем net-http-digest_auth (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

2 ответа

Я закончил тем, что использовал гем httpclient для достижения той же цели.

Окончательный код, чтобы сделать именно то, что я был после:

#!/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

Я надеюсь, что это поможет другим, которые могут работать с сервером домашней автоматизации и нуждаются в простой аутентификации на основе дайджеста.

Сет, я столкнулся с этой же проблемой, работая над сценарием в ruby. Я новичок в ruby, но после нескольких поисков в Google и некоторых прокси-серверов Charles, показывающих мне, что происходит, я вижу, что для реализаций HTTP характерно включать кавычки в часть алгоритма ="MD5" заголовка Auth, что неверно согласно спецификации (это должен быть алгоритм =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

...

Здесь важно то, что мы модифицируем строку www-authenticate, которая возвращается из вашего первоначального неавторизованного запроса 401 (как интерпретируется этой библиотекой ruby). Отправка измененной строки заголовка (www_auth_response) в метод digest_auth.auth_header не приводит к ошибкам. По крайней мере, это сработало для меня в моем сценарии!

Надеюсь, это поможет!

Matt

Другие вопросы по тегам