Getting Mechanize :: UnauthorizedError: 401 => Net :: HTTPUnauthorized при доступе к API с базовой аутентификацией - PullRequest
0 голосов
/ 13 марта 2019

Я пытаюсь получить доступ к API с помощью обычной аутентификации. Он работает с HTTParty, но не с 2.7.6 Mechanize.

Вот что я пробовал:

agent = Mechanize.new
agent.log = Logger.new(STDERR)
agent.add_auth("https://website.net/listingapi", "user", "pass")
page = agent.get("https://website.net/listingapi")

И вот что я получаю:

 INFO -- : Net::HTTP::Get: /listingapi
DEBUG -- : request-header: accept-encoding => gzip,deflate,identity
DEBUG -- : request-header: accept => */*
DEBUG -- : request-header: user-agent => Mechanize/2.7.6 Ruby/2.5.3p105 (http://github.com/sparklemotion/mechanize/)
DEBUG -- : request-header: accept-charset => ISO-8859-1,utf-8;q=0.7,*;q=0.7
DEBUG -- : request-header: accept-language => en-us,en;q=0.5
DEBUG -- : request-header: host => website.net
 INFO -- : status: Net::HTTPUnauthorized 1.1 401 Unauthorized
DEBUG -- : response-header: content-type => application/json; charset=utf-8
DEBUG -- : response-header: www-authenticate => Bearer, Basic realm=ListingApi
DEBUG -- : response-header: date => Wed, 13 Mar 2019 14:14:51 GMT
DEBUG -- : response-header: content-length => 61
DEBUG -- : response-header: x-xss-protection => 1; mode=block
DEBUG -- : response-header: strict-transport-security => max-age=31536000
DEBUG -- : response-header: x-content-type-options => nosniff
DEBUG -- : Read 61 bytes (61 total)
Mechanize::UnauthorizedError: 401 => Net::HTTPUnauthorized for https://website.net/listingapi/ -- no credentials found, provide some with #add_auth -- available realms: 
from /Users/nk/.rvm/gems/ruby-2.5.3@mygems/gems/mechanize-2.7.6/lib/mechanize/http/agent.rb:749:in `response_authenticate'

Что я делаю не так или что не так с ответом API?

PS. Я нашел это, которое, я думаю, может быть связано: https://github.com/sparklemotion/mechanize/pull/442

1 Ответ

2 голосов
/ 18 марта 2019

Когда используется базовая аутентификация, имя пользователя и пароль объединяются, а затем кодируются с использованием base64.Закодированная приведенная строка отправляется на сервер в заголовке Authorization с использованием Basic

Теперь можно обойти эту проблему, если у вас возникли проблемы с использованием add_auth, - самостоятельно передать заголовок авторизации.:

username = 'Radu'
password = 'mypassword'
agent = Mechanize.new do |agent|
  agent.pre_connect_hooks << lambda { |agent, request| request["Authorization"] = "Basic #{Base64.strict_encode64(username + ':' + password)}" }
end
page = agent.get("https://website.net/listingapi")

Редактировать 1

Теперь, когда я снова читаю журналы, я вижу, что заголовок www-authenticate говорит Bearer, Basic realm=ListingApi.Вместо этого следует сказать Basic realm=ListingApi.

Проблема в том, что response_authenticate не может найти какой-либо вызов, скорее всего, потому что запрашиваемый API не учитывает эту часть RFC7235 в отношении вызова.

Отсутствующий вызов поднимается на 401 после этой строки

[1] pry(main)> authenticate_parser  = Mechanize::HTTP::WWWAuthenticateParser.new
=> #<Mechanize::HTTP::WWWAuthenticateParser:0x00007fe2a5c74ec8 @scanner=nil>

[2] pry(main)> authenticate_parser.parse "Basic realm=ListingApi"
=> [#<struct Mechanize::HTTP::AuthChallenge scheme=nil, params=nil, raw=nil>]

[3] pry(main)> authenticate_parser.parse "Bearer, Basic realm=ListingApi"
=> []

Редактировать 2

Причина, по которой HTTParty работает, заключается в том, что они добавляют Заголовок авторизации заранее непосредственно в Net :: HTTP :: Get.Механизация использует всю авторизацию вызов-ответ, и они будут добавлять ее, только если схема вызова Basic.

...