NMHTTPの認証について教えてください。
NMHttp1.HeaderInfo.UserID:=UserID;
NMHttp1.HeaderInfo.Password:=Password;
このような設定で制限されたページへアクセスできていましたが、
管理者の説明では、Basic認証になってサーバー環境がWindows+ASPからPHP&MySQLに変わったということですがアクセスできなくなりました。
Googleの調査では、Basic 認証は、BASE 64エンコードされた認証情報を
http ヘッダに埋め込んでいるだけなので、最初から Basic 認証用のヘッダを
http ヘッダに記述しておけば、401 を返されることなくコンテンツにアクセスできるとありますが、SendHeaderの設定などどなたか教えてください。
あてずっぽうですが
NMHTTP1.SendHeader.Values['Authorization'] := 'Basic ' + BASE64でエンコードしたuser:password;
みたいな感じでしょうか。
BASE64へのエンコードは、jconvertが有名ですね。
JConvertまで教えて頂いてありがとうございます。
朝までいろいろやってみましたが、やはりNGでした。
NMHTTP1.SendHeader.Values['Authorization'] := 'Basic '
+EncodeBase64(User)+':'+EncodeBase64(Password);
EncodeBase64(':')までTryしましたが、NGです。
今までNMHTTPでアクセスできていたので、他のコンポーネントは
使っていなかったのですが、他に制限尽き(Basic)ページへアクセスできる
コンポーネント、方法をご存知ありませんか。
WinInetで可能ならTryしてみるつもりですが。
ふと気になったのですが、
user:password 全体を1回でエンコードするのではないでしょうか?
> コンポーネント、方法をご存知ありませんか。
IndyのidHttpコンポーネントはどうでしょう。
http://onigiri.s3.xrea.com:8080/delphi/index.php?Indy
さゆみん: 「あの〜、user:password 全体を1回でエンコードしてみたンです。そしたら…」
エリック: 「そうしたら、うまくいった?」
さゆみん: 「それが…、そうしても〜ダメなんですよ。どうしてでしょ♪?」
エリック: 「ン?それでもダメ? OnAboutToSendイベントで、SendHeader.Values[]:=を使って追加したの?」
さゆみん: 「モチロン、そうですよ。でもヤッパリ認証されないんです…」
エリック: 「そんなハズないよ〜、一応ヘッダ調べてみたら?」
さゆみん: 「ヘッダを見ると、チャンと'Authorization: Basic *****'って入ってます〜」
エリック: 「オカシイな〜、間違いなくBASE64エンコードもされてるのに…」
なかざわ: 「おまえら、そのヘッダ、よ〜く見てみんかい」
エリック: 「さっきから穴があくほど見つめてるんですけど…」
さゆみん: 「ワタシも何回も見なおしてます。でも〜」
なかざわ: 「まったく、おまえらの目、フシアナやな」
さゆみん: 「え〜?このツブラな瞳をフシアナだなんてヒドイ♪」
なかざわ: 「…、'Authorization: …'の行の前、ナンかあるやろ」
エリック: 「その行の前は…何もない空の行ですよね」
さゆみん: 「あの〜、もしかして…それがマズイとか♪?」
なかざわ: 「そやな〜、マズイかもしれんで」
エリック: 「だけど、追加すると自動的に空行が前に入っちゃうんですよ」
さゆみん: 「じゃぁ、どうしようもないですよね。NMHTTPって、イ・ジ・ワ・ル♪」
なかざわ: 「…」
エリック: 「打つ手なしですか。なら、NMHTTPはアキラメましょ」
なかざわ: 「もうアキラメる? …ところで、おまえらヘルプもヨウ見とらんようやな」
エリック: 「ヘルプ?なにか…ありましたっけ?」
なかざわ: 「HeaderInfoプロパティの中にUserID、Passwordちゅうエエもんあるんやけどな〜」
エリック: 「えッ!?ソレ早く言ってくださいよ。ンもう、あいかわらず…」
なかざわ: 「なんや?! ”あいかわらず”ナンやっチュウねん!!」
エリック: 「いっいいえ、ワタシなにも言ってませんよ〜(^^;;;」
八っつぁん: 「おやおや、結局BASE64エンコードされた認証情報をヘッダに埋め込むのは、HeaderInfoのUserIDなどを設定するのと一緒なんですかい?大家さん」
大家の隠居: 「そうだね、八っつぁん。HeaderInfoの設定で認証できないなら、自前でヘッダにAuthorization追加しても駄目ってことさ」
クマつぁん: 「じゃあ、どしたらいいんでしょうねぇ、大家さん」
大家の隠居: 「それは聞く相手が違うだろ。そのサイトの大家に聞いとくれな」
クマつぁん: 「あっそれも道理で。どこだかわかんねぇことにはどうしようもねぇってことですねぇ、大家さん」
>user:password 全体を1回でエンコードするのではないでしょうか?
これもNGでした。
>IndyのidHttpコンポーネントはどうでしょう。
>http://onigiri.s3.xrea.com:8080/delphi/index.php?Indy
WinInetもNGだったので、idHttpにTryしてみます。
D6にはHELPもないため躊躇していたのですが止むを得ないですね。
そもそも、DelphiのNMHTTPがBasic認証をサポートしていない
可能性が高いとの情報もありました。 idHttpは又報告します。
>そもそも、DelphiのNMHTTPがBasic認証をサポートしていない
そんなことないです。
>NMHttp1.HeaderInfo.UserID:=UserID;
>NMHttp1.HeaderInfo.Password:=Password;
これで認証できないのなら、そのサイトの認証方式がBasic認証ではないということでしょう。
>>NMHttp1.HeaderInfo.UserID:=UserID;
>>NMHttp1.HeaderInfo.Password:=Password;
>これで認証できないのなら、そのサイトの認証方式がBasic認証ではないとい>うことでしょう。
そうですか、先方はBasic認証に変更したという話ですので、再度確認してみます。 情報ありがとうございます。
アクセス先のページがBasic認証のほかリダイレクトをしていたためNMHttpでは不可でした。 NMHttpの代わりにIndy10による下記のコードで取得出来るようになりました。
var File,URL: string;
fs: TFileStream;
begin
try
File:=保存先フォルダー+ファイル名';
URL :=アドレス+ファイル名;
fs := TFileStream.Create(File, fmCreate);
IdHttp1.Request.Clear;
Idhttp1.HandleRedirects := true; //リダイレクト
Idhttp1.Request.BasicAuthentication:=true; //Basic認証
Idhttp1.Request.UserName:=ID;
Idhttp1.Request.Password:=PW;
Idhttp1.Get(file, fs);
finally
fs.Free;
end;
end;
>アクセス先のページがBasic認証のほかリダイレクトをしていたためNMHttpでは不可でした。
誤解があるかもしれないのでコメントしますが、NMHttpもリダイレクトには対応しています。
ただし、Basic認証がリダイレクトされている場合、NMHttpではヘッダの
Authorization:…
の前に空行が入ってしまうため認証できなくなるようですね。
※Indyの場合にはリダイレクトされてもヘッダに空行は入りません。
解決しているのでいまさらですが、NMHttpのヘッダを見ると
リダイレクト後のGETメソッドの時に
GET /data/filename.dat HTTP/1.0[CR・LF]
と行くべきところが、
GET /data/filename.dat[CR・LF]HTTP/1.0[CR・LF]
と間にCR・LF(空行)が入ってしまうようです。
HTTP/1.0の行が出来てしまいますが、以降にHost:・・・・やAuthorization:・・・
など、ちゃんとヘッダ情報もあるのですが、サーバからは404エラーが返る
ので、次の Host: xxxxx.com を認識できなくなっているようです。
普通にHTTP手順でLogを取ると、GETメソッド以降はHTTPとして認識しなくて
認証データを付けていないように見えましたが、バイナリでチェックをすると
上記の2バイト以外は正常のようです。
最初にDLを指定する時のGETメソッドは正常なので、これはNMHTTPのバグでしょうね。
IndyでLogを取ると最初のGET→ 302→ 2度めのGETで終わるのが
NMHTTPだと、リダイレクトするまで10回以上のやり取りがありますね、
やっぱり、HTTP/1.1のIndyを使うのが正解でしょう。
ツイート | ![]() |