DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

認証が必要なページをダウンロードする

ここでは、認証が必要なHTTPページ(ユーザー名とパスワードが必要なページ)をHttpWebRequestクラスを使ってダウンロードする方法を紹介します。

HttpWebRequest.Credentialsプロパティ + NetworkCredentialを使用する

そのためには、HttpWebRequest.Credentialsプロパティを使用します。Credentialsプロパティには、NetworkCredentialまたはCredentialCacheオブジェクトを指定できます(CredentialCacheの場合も、ユーザーやパスワードの情報はNetworkCredentialで指定します)。MSDNによると、NetworkCredentialクラスは、基本認証(Basic)、ダイジェスト認証(Digest)、NTLM認証、Kerberos認証などに対応しており、SSLクライアント認証などの公開キーに基づく認証方式はサポートしていないとのことです。

次の例では認証が必要なページ"http://localhost/index.html"のユーザー名が"username"、パスワードが"password"として、ページの内容を取得しています。

VB.NET
コードを隠すコードを選択
'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()
C#
コードを隠すコードを選択
//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プロパティでも同様に、認証の方法を指定してダウンロードすることができます。

CredentialCacheを使用する

上記の方法では、例えばHttpWebRequest.AllowAutoRedirectプロパティがTrue(デフォルト値)で、リダイレクトに自動的に対応している場合などでは、うまく行かないことがあるようです。そのような場合は、NetworkCredentialの代わりにCredentialCacheを使うとよいようです。

以下に、NetworkCredentialの代わりにCredentialCacheを使用した例を示します。ここでは、基本認証(Basic)の情報のみを追加していますが、別の認証方式(MSDNに記述がないため詳細は不明ですが、NTLM、Digest、Kerberos、Negotiateが可能かと思われます)を追加することもできます。

VB.NET
コードを隠すコードを選択
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()
C#
コードを隠すコードを選択
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();

2回目以降、Authorizationヘッダを付けて送信する

上記の方法では、HttpWebRequestはまずAuthorizationヘッダを付けずにリクエストを送信し、401 Unauthorizedが返ってきたら、今度はAuthorizationヘッダを付けて送信しなおします。しかし、認証が必要と分かっているページであれば、はじめからAuthorizationヘッダを付けてリクエストを送信した方が効率的です。

HttpWebRequest.PreAuthenticateプロパティをTrueにすると、一番初めのリクエストにはAuthorizationヘッダが付きませんが、2回目以降はAuthorizationヘッダが付くようになります。

例えば、一番初めに紹介したコードにPreAuthenticateプロパティを変更できるコードを追加して、以下のようなメソッドを作ったとします。

VB.NET
コードを隠すコードを選択
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
C#
コードを隠すコードを選択
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)」として複数回連続で呼び出すと、今まで通り、

  1. Authorizationヘッダを付けずにリクエストを送信
  2. Authorizationヘッダを付てリクエストを送信

ということを、「PrintHtml(false)」を呼び出した回数だけ繰り返します。

しかし、「PrintHtml(true)」として複数回連続で呼び出した時は、はじめの1回は

  1. Authorizationヘッダを付けずにリクエストを送信
  2. Authorizationヘッダを付てリクエストを送信

となりますが、それ以後の「PrintHtml(true)」では、

  1. Authorizationヘッダを付てリクエストを送信

だけになります。

はじめからAuthorizationヘッダを付けて要求する

はじめからAuthorizationヘッダを付けて要求するには、自分でヘッダを付けるしかないようです。この方法では、自分でAuthorizationヘッダの内容を決定しなければならないため、複雑な認証方式の場合は、面倒です。

基本認証の場合は比較的簡単で、以下のようなコードでできます。

VB.NET
コードを隠すコードを選択
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()
C#
コードを隠すコードを選択
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();
  • 履歴:
  • 2016/8/28 「CredentialCacheを使用する」、「2回目以降、Authorizationヘッダを付けて送信する」、「はじめからAuthorizationヘッダを付けて要求する」を追加。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。