SVX日記

2004|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|

2024-09-11(Wed) RubyでDigest認証クライアントを作らせる

  昨日、RubyでDigest認証クライアントを作ったわけだが、ふと、流行りのAIのお手並みでも拝見してみようかと思いついた。

  で、そのまんま「httpクライアントとして、digest認証を行い、htmlを受信するRubyスクリプトを書いてください」と問い合わせてみる。それに対する回答は以下。

もちろん、以下はRubyでHTTPクライアントとしてDigest認証を行い、HTMLを受
信する簡単なスクリプトの例です。このスクリプトでは、net/httpライブラリ
とnet/http/digest_authライブラリを使用します。
 
まず、必要なライブラリをインストールしてあることを確認してください。
 
require 'net/http'
require 'net/http/digest_auth'
require 'uri'
 
以下がスクリプトの例です:
 
require 'net/http'
require 'net/http/digest_auth'
require 'uri'
 
# 認証情報を設定
uri = URI('http://example.com/protected')
username = 'your_username'
password = 'your_password'
 
# ネットワーク接続の設定
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = (uri.scheme == "https")
 
# 初回リクエストを送信して、401 Unauthorizedレスポンスを受け取る
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
 
# Digest Auth用の認証ヘッダを作成
digest_auth = Net::HTTP::DigestAuth.new
auth_header = digest_auth.auth_header(uri, response['www-authenticate'], 'GET', username, password)
 
# 認証ヘッダを追加し、再度リクエストを送信
request = Net::HTTP::Get.new(uri.request_uri)
request['Authorization'] = auth_header
response = http.request(request)
 
# レスポンスの表示
puts response.body
 
このスクリプトでは、次のステップを行います:
 
  抽出用にURIオブジェクトを作成し、認証情報を設定します。
  最初のリクエストを送信して、401 Unauthorizedレスポンスを受け取ります。
  401 UnauthorizedレスポンスからDigest認証用のヘッダ情報を取り出し、新
  しいリクエストに対して認証ヘッダを作成します。
  再度リクエストを送信して、認証後のページ内容(HTML)を取得します。
 
このスクリプトを実行する際は、適切なURL、ユーザー名、パスワードに置き
換えてください。また、サーバーがHTTPSを使っている場合は、http.use_ssl
をtrueに設定してください。

  ほら、出たよ。もっともらしく、ありもしない「net/http/digest_auth」を使ったりして……って、んッ!? もしかして、RubyGemsにあったりするのか!?

$ gem search digest | grep http
net-http-digest_auth (1.4.1)

  それっぽいのがあるなぁ……インストールしてみよう。

$ bundle init
$ bundle add net-http-digest_auth

  書いてもらったコードをそのまま動かしてみる……が、エラーが出た。

$ bundle exec ./digest_test
ArgumentError: wrong number of arguments (given 5, expected 3..4)
  /home/user/develop/digest_auth/vendor/bundle/ruby/2.6.0/gems/net-http-digest_auth-1.4.1/lib/net/http/digest_auth.rb:76:in `auth_header'
  /home/user/develop/digest_auth/digest_test:22:in `<top (required)>'

  しかし、完全に的外れっぽいエラーのようには見えない。ライブラリのコードを確認してみる。

def auth_header uri, www_authenticate, method, iis = false
  nonce_count = next_nonce
  user     = CGI.unescape uri.user
  password = CGI.unescape uri.password

  ライブラリの側ではusernameとpasswordをuriインスタンスから得る形になっている。これは後から修正したっぽい感じだな。もしかしたら、前のバージョンなら動いたのかもしれない。直してやる。

$ diff digest_test.org digest_test
9,10c9,10
< username = 'your_username'
< password = 'your_password'
---
> uri.user = 'your_username'
> uri.password = 'your_password'
22c22
< auth_header = digest_auth.auth_header(uri, response['www-authenticate'], 'GET', username, password)
---
> auth_header = digest_auth.auth_header(uri, response['www-authenticate'], 'GET')

  なんとッ!! これだけの修正で動いてしまった。おぉ……なんというか、やるなぁ。ここまで来ているんだなぁ。素直に、スゴい。ダメ出ししてやるつもりだったのに、当てが外れてしまった。

  そもそも、RubyGemsも探さずに、検索でもうまく見つけられなかった自分も不甲斐ないが、それ込みで回答内容には誤った部分はなく非常に有用だ。ちょっと悔しいくらいだな。コードの記述方法は自分が書いたスタイルのほうが圧倒的に美しいと思うが、それはライブラリに対する難クセであって、回答内容とは関係ない。あまり粘着するとラッダイト野郎になるしな。ここは素直に認めておこう。

  でもね。別にいいのだよ。いくら自動運転が発達しようと運転するのは楽しいし、いくらボーカロイドが発達しようと歌うのは楽しいし、いくら将棋AIが発達しようと将棋を指すのは楽しいのだろうし、いくらコード生成AIが発達しようとプログラミングは楽しいのだ。そう。自分にとってプログラミングは仕事じゃないので。

  しかし正直、複雑な気分ではあるなぁ……。