8
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Open-uriの認証とリダイレクト

Posted at

にゃんぱすー

Open-uri による認証と問題点

Open-uri を使用する場合、open:http_basic_authentication オプションでユーザ名とパスワードを与えることで認証付のURLにアクセスすることができる。

fh = open(
  uri,
  :http_basic_authentication => [user, password],
)

その際、アクセス先がリダイレクト (3xx) のステータスを返し、リダイレクト先URLが認証を要求する場合には、常に "401 Unauthorized" の例外 (OpenURI::HTTPError) が発生する。これは同一の認証情報でアクセス可能な場合でも同様である。

原因

open-uri ではリダイレクトが行われた場合には、無条件で :http_basic_authentication を削除しているため。(Perl の LWP とは動作が異なる。)

open-uri.rb
if redirect
  ...
  if options.include? :http_basic_authentication
    # send authentication only for the URI directly specified.
    options = options.dup
    options.delete :http_basic_authentication
  end

解決策

リダイレクトされる可能性のあるURIに認証情報を渡す場合は、リダイレクトを無効化 (:redirect => false) した上で、自前でリダイレクトを処理する必要がある。

redirectable? は必要に応じて修正すること。

require "open-uri"

def redirectable?(orig_uri, new_uri)
  orig_uri.scheme == new_uri.scheme and
  orig_uri.host == new_uri.host and
  orig_uri.port == new_uri.port
end

uri = URI("http://www.example.com/")
user = "fate"
password = "nanoha"
max_redirects = 10
num_redirects = 0

begin
  fh = open(
    uri,
    :http_basic_authentication => [user, password],
    :redirect => false
  )
rescue OpenURI::HTTPRedirect => redirect
  num_redirects += 1

  if num_redirects <= max_redirects and redirectable?(uri, redirect.uri)
    uri = redirect.uri
    retry
  else
    raise redirect
  end
end
8
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?