ここでは、認証が必要なHTTPページ(ユーザー名とパスワードが必要なページ)をHttpWebRequestクラスを使ってダウンロードする方法を紹介します。
そのためには、HttpWebRequest.Credentialsプロパティを使用します。Credentialsプロパティには、NetworkCredentialまたはCredentialCacheオブジェクトを指定できます(CredentialCacheの場合も、ユーザーやパスワードの情報はNetworkCredentialで指定します)。MSDNによると、NetworkCredentialクラスは、基本認証(Basic)、ダイジェスト認証(Digest)、NTLM認証、Kerberos認証などに対応しており、SSLクライアント認証などの公開キーに基づく認証方式はサポートしていないとのことです。
次の例では認証が必要なページ"http://localhost/index.html"のユーザー名が"username"、パスワードが"password"として、ページの内容を取得しています。
'HttpWebRequestの作成 Dim webreq As System.Net.HttpWebRequest = _ CType(System.Net.WebRequest.Create("http://localhost/index.html"), _ System.Net.HttpWebRequest) '認証の設定 webreq.Credentials = New System.Net.NetworkCredential("username", "password") 'HttpWebResponseの取得 Dim webres As System.Net.HttpWebResponse = _ CType(webreq.GetResponse(), System.Net.HttpWebResponse) '受信して表示 Dim st As System.IO.Stream = webres.GetResponseStream() Dim sr As New System.IO.StreamReader(st) Console.WriteLine(sr.ReadToEnd()) '閉じる sr.Close() st.Close()
//HttpWebRequestの作成 System.Net.HttpWebRequest webreq = (System.Net.HttpWebRequest) System.Net.WebRequest.Create("http://localhost/index.html"); //認証の設定 webreq.Credentials = new System.Net.NetworkCredential("username", "password"); //HttpWebResponseの取得 System.Net.HttpWebResponse webres = (System.Net.HttpWebResponse) webreq.GetResponse(); //受信して表示 System.IO.Stream st = webres.GetResponseStream(); System.IO.StreamReader sr = new System.IO.StreamReader(st); Console.WriteLine(sr.ReadToEnd()); //閉じる sr.Close(); st.Close();
なお、NetworkCredentialコンストラクタの3番目のパラメータにユーザー名が属するドメインまたは領域を指定することもできます。
ここではHttpWebRequest、HttpWebResponseクラスを使用しましたが、WebClientクラスのCredentialsプロパティでも同様に、認証の方法を指定してダウンロードすることができます。
上記の方法では、例えばHttpWebRequest.AllowAutoRedirectプロパティがTrue(デフォルト値)で、リダイレクトに自動的に対応している場合などでは、うまく行かないことがあるようです。そのような場合は、NetworkCredentialの代わりにCredentialCacheを使うとよいようです。
以下に、NetworkCredentialの代わりにCredentialCacheを使用した例を示します。ここでは、基本認証(Basic)の情報のみを追加していますが、別の認証方式(MSDNに記述がないため詳細は不明ですが、NTLM、Digest、Kerberos、Negotiateが可能かと思われます)を追加することもできます。
Dim url As String = "http://localhost/index.html" 'HttpWebRequestの作成 Dim webreq As System.Net.HttpWebRequest = _ DirectCast(System.Net.WebRequest.Create(url), System.Net.HttpWebRequest) 'CredentialCacheの作成 Dim cache As New System.Net.CredentialCache() '基本認証の情報を追加 cache.Add(New Uri(url), _ "Basic", _ New System.Net.NetworkCredential("username", "password")) '認証の設定 webreq.Credentials = cache 'HttpWebResponseの取得 Dim webres As System.Net.HttpWebResponse = _ DirectCast(webreq.GetResponse(), System.Net.HttpWebResponse) '受信して表示 Dim st As System.IO.Stream = webres.GetResponseStream() Dim sr As New System.IO.StreamReader(st) Console.WriteLine(sr.ReadToEnd()) '閉じる sr.Close() st.Close()
string url = "http://localhost/index.html"; //HttpWebRequestの作成 System.Net.HttpWebRequest webreq = (System.Net.HttpWebRequest) System.Net.WebRequest.Create(url); //CredentialCacheの作成 System.Net.CredentialCache cache = new System.Net.CredentialCache(); //基本認証の情報を追加 cache.Add(new Uri(url), "Basic", new System.Net.NetworkCredential("username", "password")); //認証の設定 webreq.Credentials = cache; //HttpWebResponseの取得 System.Net.HttpWebResponse webres = (System.Net.HttpWebResponse)webreq.GetResponse(); //受信して表示 System.IO.Stream st = webres.GetResponseStream(); System.IO.StreamReader sr = new System.IO.StreamReader(st); Console.WriteLine(sr.ReadToEnd()); //閉じる sr.Close(); st.Close();
上記の方法では、HttpWebRequestはまずAuthorizationヘッダを付けずにリクエストを送信し、401 Unauthorizedが返ってきたら、今度はAuthorizationヘッダを付けて送信しなおします。しかし、認証が必要と分かっているページであれば、はじめからAuthorizationヘッダを付けてリクエストを送信した方が効率的です。
HttpWebRequest.PreAuthenticateプロパティをTrueにすると、一番初めのリクエストにはAuthorizationヘッダが付きませんが、2回目以降はAuthorizationヘッダが付くようになります。
例えば、一番初めに紹介したコードにPreAuthenticateプロパティを変更できるコードを追加して、以下のようなメソッドを作ったとします。
Public Shared Sub PrintHtml(preAuthenticate As Boolean) 'HttpWebRequestの作成 Dim webreq As System.Net.HttpWebRequest = _ DirectCast(System.Net.WebRequest.Create("http://localhost/index.html"), _ System.Net.HttpWebRequest) 'PreAuthenticateプロパティを設定 webreq.PreAuthenticate = preAuthenticate '認証の設定 webreq.Credentials = New System.Net.NetworkCredential("username", "password") 'HttpWebResponseの取得 Dim webres As System.Net.HttpWebResponse = _ DirectCast(webreq.GetResponse(), System.Net.HttpWebResponse) '受信して表示 Dim st As System.IO.Stream = webres.GetResponseStream() Dim sr As New System.IO.StreamReader(st) Console.WriteLine(sr.ReadToEnd()) '閉じる sr.Close() st.Close() End Sub
public static void PrintHtml(bool preAuthenticate) { //HttpWebRequestの作成 System.Net.HttpWebRequest webreq = (System.Net.HttpWebRequest) System.Net.WebRequest.Create("http://localhost/index.html"); //PreAuthenticateプロパティを設定 webreq.PreAuthenticate = preAuthenticate; //認証の設定 webreq.Credentials = new System.Net.NetworkCredential("username", "password"); //HttpWebResponseの取得 System.Net.HttpWebResponse webres = (System.Net.HttpWebResponse)webreq.GetResponse(); //受信して表示 System.IO.Stream st = webres.GetResponseStream(); System.IO.StreamReader sr = new System.IO.StreamReader(st); Console.WriteLine(sr.ReadToEnd()); //閉じる sr.Close(); st.Close(); }
このメソッドを「PrintHtml(false)」として複数回連続で呼び出すと、今まで通り、
ということを、「PrintHtml(false)」を呼び出した回数だけ繰り返します。
しかし、「PrintHtml(true)」として複数回連続で呼び出した時は、はじめの1回は
となりますが、それ以後の「PrintHtml(true)」では、
だけになります。
はじめからAuthorizationヘッダを付けて要求するには、自分でヘッダを付けるしかないようです。この方法では、自分でAuthorizationヘッダの内容を決定しなければならないため、複雑な認証方式の場合は、面倒です。
基本認証の場合は比較的簡単で、以下のようなコードでできます。
Dim url As String = "http://localhost/index.html" Dim username As String = "username" Dim password As String = "password" 'HttpWebRequestの作成 Dim webreq As System.Net.HttpWebRequest = _ DirectCast(System.Net.WebRequest.Create(url), System.Net.HttpWebRequest) '基本認証のAuthorizationヘッダを追加する webreq.Headers("Authorization") = "Basic " & _ Convert.ToBase64String( _ System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes( _ username & ":" & password)) 'HttpWebResponseの取得 Dim webres As System.Net.HttpWebResponse = _ DirectCast(webreq.GetResponse(), System.Net.HttpWebResponse) '受信して表示 Dim st As System.IO.Stream = webres.GetResponseStream() Dim sr As New System.IO.StreamReader(st) Console.WriteLine(sr.ReadToEnd()) '閉じる sr.Close() st.Close()
string url = "http://localhost/index.html"; string username = "username"; string password = "password"; //HttpWebRequestの作成 System.Net.HttpWebRequest webreq = (System.Net.HttpWebRequest) System.Net.WebRequest.Create(url); //基本認証のAuthorizationヘッダを追加する webreq.Headers["Authorization"] = "Basic " + Convert.ToBase64String( System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes( username + ":" + password)); //HttpWebResponseの取得 System.Net.HttpWebResponse webres = (System.Net.HttpWebResponse)webreq.GetResponse(); //受信して表示 System.IO.Stream st = webres.GetResponseStream(); System.IO.StreamReader sr = new System.IO.StreamReader(st); Console.WriteLine(sr.ReadToEnd()); //閉じる sr.Close(); st.Close();