C# で Web サイトにログインする

Syed Hassan Sabeeh Kazmi 2023年10月12日
  1. C#WebClient を使用して Web サイトにログインする
  2. C# で Web サイトにログインするスクリプトを作成する
  3. C#Selenium を自動化して Web サイトにログインするスクリプトを作成する
  4. C#HttpClient を使用して Web サイトにログインする
C# で Web サイトにログインする

このチュートリアルでは、C# でプログラムによって Web サイトにログインするための最適化された方法を学び、理解します。 ASP.NET C# を使用して外部 Web サイトに自動ログインすることが可能です。Web サイトが HTTP POST を使用してログインを検証する場合は、post メソッドを外部で使用できます。

Visual Studio は proxy class web server メソッドを呼び出して自動的にプロキシを生成するため、サービス参照を C# プロジェクトに追加するのが一般的な方法です。 ただし、プログラマティックは Web サーバーを呼び出して認証するための最適な方法です。

C#WebClient を使用して Web サイトにログインする

ウェブサイトへのプログラムによるログインの最善の方法は、WebClientPOST に使用することです。 POST (初心者レベルの開発者にとっては非常に複雑なため) の確実な代替は、下位レベルの WebRequest および WebResponse クラスです。

ログイン フォームの作成は、このアプローチの 2つの主要な部分の 1つであり、2つ目は、GET リクエストを使用して Set-cookie ヘッダーを回復することです。 GET リクエストと一緒に送信した Cookie としての Set-cookie ヘッダーが、応答するサーバーによって認識された場合、サーバーが Cookie ベースの認証を使用している場合にのみ、それ以降はあなたを識別します。

GET には次の C# コードを使用します。

public static string HttpGet(string web_URI) {
  System.Net.WebRequest web_request = System.Net.WebRequest.Create(web_URI);

  // the following means no proxy for the website
  web_request.Proxy = new System.Net.WebProxy(ProxyString, true);

  System.Net.WebResponse web_response = web_request.GetResponse();

  System.IO.StreamReader stream_reader =
      new System.IO.StreamReader(web_response.GetResponseStream());

  return stream_reader.ReadToEnd().Trim();
}

SET には次の C# コードを使用します。

public static string HttpPost(string web_URI, string web_para) {
  System.Net.WebRequest web_request = System.Net.WebRequest.Create(web_URI);
  web_request.Proxy = new System.Net.WebProxy(ProxyString, true);

  // add the following as you are doing the `POST`
  web_request.ContentType = "your_application/insert-the-form-rncoded-URL";
  web_request.Method = "POST";  // SET

  // it's important to know how many bytes you are transforming or sending to the server.
  // Remember | Post'ed Faked Forms should be `name=value&`
  byte[] sending_bytes = System.Text.Encoding.ASCII.GetBytes(web_para);
  web_request.ContentLength = sending_bytes.Length;

  System.IO.Stream web_stream = web_request.GetRequestStream();

  // you can push the bytes here
  web_stream.Write(sending_bytes, 0, sending_bytes.Length);
  web_stream.Close();

  System.Net.WebResponse web_response = web_request.GetResponse();
  if (web_response == null)
    return null;

  System.IO.StreamReader stream_reader =
      new System.IO.StreamReader(web_response.GetResponseStream());

  return stream_reader.ReadToEnd().Trim();
}

次のような方法で投稿データを簡単にフォーマットできるため、フォーム投稿は簡単にシミュレートできます。

field_1 = value_1 & field_2 = value_2

このメソッドのサンプル C# WebClient コードは、WebRequest を使用して Web サイトにログインするための Scott Hanselman アプローチを反映しています。

さらに、次の C# コードは、プログラムで Web サイトにログインするために Scott Hanselman によって作成されたアプローチを表しています。

// the `web_URL` represents the `POST` URL instead of the `form` URL
// to access `form` URL, find the `action` attribute of the HTML's `form` tag
string web_URL =
    "http://www.examplewebsite.com/index.do?PageModule=UserAccess&Modification=UsersVerificationviaLogin";

string parameter_form = string.Format("example_format(email_address={0}&password={1})",
                                      "my_email_address", "my_password");

// create a header cookie
string header_cookie;

// create a request object from the `WebRequest`
WebRequest web_request = WebRequest.Create(web_URL);

// define its content type and method
web_request.ContentType =
    "yourC#application/x-www_address-form-encoded_url";  // or something like
                                                         // "application/x-www-form-urlencoded"
web_request.Method = "POST";  // as it's a request, so the method will be POST

// access the `parameter_form` to convert it into bytes (sending it to the server)
byte[] sending_bytes = Encoding.ASCII.GetBytes(parameter_form);
web_request.ContentLength = sending_bytes.Length;  // define its length

using (Stream web_stream = web_request.GetRequestStream()) {
  // for web requests or requests to the server for login
  web_stream.Write(sending_bytes, 0, sending_bytes.Length);
}

// create a `WebResponse` object to receive or understand the response from the corresponding server
WebResponse web_response = web_request.GetResponse();
header_cookie = web_response.Headers["Set-cookie"];  // `Set-cookie` as a web response header file

/*
    GET
*/

// define a source page and the `GET` web URL
string source_page;
string web_URL_get =
    "http://www.webpage_behind_the_login.com";  // mention the webpage behind the login form

// create a GET response
WebRequest web_request_get = WebRequest.Create(web_URL_get);
web_request_get.Headers.Add("Cookie", header_cookie);

// web_request_get.ContentLength = web_request.ContentLength;
WebResponse web_response_get = web_request_get.GetResponse();

using (StreamReader stream_reader_get = new StreamReader(web_response_get.GetResponseStream())) {
  source_page = stream_reader_get.ReadToEnd();
}

以下は、C# プロジェクトにコピーして貼り付け、WebClient を使用して Web サイトにログインできる C# コードです。 ただし、自分のユーザー名とパスワードを使用し、Web サイトの URL を入力することを忘れないでください。また、ログインに成功した後に C# プログラムがリダイレクトする Web ページについても忘れずに言及してください。

using System;
using System.Windows.Forms;
using System.Net;
// using System.Net.Http;
using System.Collections.Specialized;

namespace test_login {
  // create a sub-class using `WebClient`
  public class CookieAwareWebClient : WebClient {
    // create a cookie container for web requests and web response
    private CookieContainer website_cookie = new CookieContainer();

    // overload using URI of the target web address
    protected override WebRequest GetWebRequest(Uri trg_web_add) {
      WebRequest tag_web_request = base.GetWebRequest(trg_web_add);
      if (tag_web_request is HttpWebRequest) {
        (tag_web_request as HttpWebRequest).CookieContainer =
            website_cookie;  // generate a proper request to the server
      }
      return tag_web_request;
    }
  }
  public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e) {
      // create a new user
      var new_user = new CookieAwareWebClient();

      // base address of the corresponding webpage (for login)
      new_user.BaseAddress = @"https://www.example_website/some_page/login/url_address/";

      // create a variable that carries the user information
      var user_info = new NameValueCollection();
      user_info.Add("username", "your_username");  // username or mail address
      user_info.Add("password", "your_password");  // password

      // upload the user information to the webpage
      new_user.UploadValues("login_page.php", "POST", user_info);

      // successfully login can request the pages, following
      string source_html = new_user.DownloadString("website_homepage.php");
    }
  }
}

出力:

username: your_username
password: your_password

[redirect the user to the `index.php` after a successful login]

もう 1つの興味深いアイデアは、WebClient から派生するクラスを作成してオーバーライドした後、GetWebRequest メソッドに CookieContainer オブジェクトを設定して、このアプローチを変更することです。 単一または同じ CookieContainer インスタンスは、デフォルトで Cookie 管理を処理できます。

C# で Web サイトにログインするスクリプトを作成する

プログラムによる Web サイトへのログインは、Web サイトがログイン手順を実装する方法と密接に関連しているため、各 Web サイトのログイン手順は一意であり、異なるプロトコルが必要です。 プロセスを理解し、それに応じて (サーバーへの、およびサーバーからの) 要求と応答を記述する必要があります。

Web サイトの手順を通過する非常に複雑で壊れやすいスクリプトを作成するのは簡単なことではありませんが、そうすることで、アプリケーションのセキュリティと有効性を高めることができます。 さらに、AllowAutoRedirect をオフにして、POSTGET の両方のリクエストを同じユーザー エージェントに設定すると、次のようなことができます。

request.UserAgent = UserAgent;

// to eliminate any redirection to other website or webpage
request.AllowAutoRedirect = false;

一部の Web サイトは、ログインしようとすると暗号化された URL エンコードされた戻り値を送信します。サーバーが何かが欠けていることに気付いた場合、HTTP/1.1 400 Bad Requestのようなものをスローするか、サーバーからの 200 応答である可能性があります。 内部のどこかに埋め込まれたエラーメッセージ。 サーバーが違いを認識せずにログインできるように、適切な値を収集して HttpWebRequest オブジェクトに渡す必要があります。

using System;
using System.Windows.Forms;
using System.Net;
// using System.Net.Http;
using System.IO;
// using System.Collections.Specialized;

namespace test_login {
  public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e) {
      string user_name = UsernameBox.Username;              // textbox that contains the user name
      string user_password = PasswordBoxPassword.Password;  // textbox that contains the password

      // HTML IDs or important user information to perform a successful login against a specific
      // user
      string login_user_name = textBox1.Text;      // username
      string login_user_password = textBox2.Text;  // password

      // submit info for a successful login
      string login_submit_info = textBox3.Text;  // login submit

      // define the website or webpage connection parameters
      string post_method = "POST";  // `POST` method for web_request
      string type_webcontent = @"c_sharp-application/encoded_url-www-form";
      string string_login = login_user_name + "=" + user_name + "&" + login_user_password + "=" +
                            user_password + "&" + login_submit_info;
      CookieContainer container_cookie = new CookieContainer();
      HttpWebRequest web_request;

      web_request = (HttpWebRequest)WebRequest.Create(
          "http://www.example_url.com/login_page/");  // or insert the `url` string that contains
                                                      // the valid website URL
      web_request.CookieContainer = container_cookie;
      web_request.Method = post_method;  // for web request
      web_request.ContentType = type_webcontent;
      web_request.KeepAlive = true;

      using (Stream web_stream_request = web_request.GetRequestStream())

          // generate a proper web request
          using (StreamWriter writer = new StreamWriter(web_stream_request)) {
        writer.Write(string_login, user_name, user_password);
      }

      using (var web_stream_response = web_request.GetResponse().GetResponseStream()) using (
          var web_response_reader = new StreamReader(web_stream_response)) {
        var user_check = web_response_reader.ReadToEnd();
        Console.WriteLine(user_check);  // the result
      }

      MessageBox.Show("Successful login to website!");
    }
  }
}

出力:

Successful login to website!

C#Selenium を自動化して Web サイトにログインするスクリプトを作成する

手動のスクリプトを作成するのは面倒なので、selenium.WebDriver を自動化するスクリプトを作成することは、プログラムで C# の Web サイトにログインするための有効なオプションです。 すべてのジャグリングを処理して、有効な Cookie を取得できるようにすることで、リクエストを正常にスローできます。

コードを最適化するには、selenium を理解することが重要です。 たとえば、azureにログインしてクレジットを取得すると、スクリプトの作成が非常に短くなります。 ただし、CookieContainer exp_cookie = new CookieContainer(); がないため、 つまり、CookieContainer をサポートする Web サイトには適していません。

// Install `Selenium.WebDriver` NuGet Package
// Install `Selenium.WebDriver.ChromeDriver` NuGet Package

using System;
using System.Windows.Forms;
using System.Net;
// using System.Net.Http;
using System.IO;
// using System.Collections.Specialized;

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;

namespace login_website {
  public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
    }
    private void button1_Click(object sender, EventArgs e) {
      // run selenium | starts from...
      ChromeDriver chrome_driver = new ChromeDriver(
          @"chromedriver_win32");  // install the selenium chrome web driver for `ChromeDriver`
      chrome_driver.Url = @"https://fif.com/login";
      chrome_driver.Navigate();
      IWebElement web_element = chrome_driver.FindElementById(
          "user_name");  // install selenium web driver to use `FindElementById()` method
      web_element.SendKeys("...");
      web_element = chrome_driver.FindElementById("user_password");
      web_element.SendKeys("...");
      web_element = chrome_driver.FindElementByXPath(
          @"//*[@id=""main""]/div/div/div[2]/table/tbody/tr/td[1]/div/form/fieldset/table/tbody/tr[6]/td/button");
      web_element.Click();

      CookieContainer cookie_container = new CookieContainer();

      // get the cookies from the website
      foreach (OpenQA.Selenium.Cookie web_cookie in chrome_driver.Manage().Cookies.AllCookies) {
        string user_name = web_cookie.Name;
        string user_value = web_cookie.Value;
        cookie_container.Add(
            new System.Net.Cookie(user_name, user_value, web_cookie.Path, web_cookie.Domain));
      }

      // generate a proper web request
      HttpWebRequest http_web_request = (HttpWebRequest)HttpWebRequest.Create(
          "https://example.com/web_content/com_example/web_tools/page_capacity/login_values/");  // or something like "https://fif.com/components/com_fif/tools/capacity/values/"
      http_web_request.CookieContainer = cookie_container;
      http_web_request.Method = "POST";
      http_web_request.ContentType = "application/x-www-form-urlencoded";

      StreamWriter stream_writer = new StreamWriter(http_web_request.GetRequestStream());
      stream_writer.Write("feeds=35");
      stream_writer.Close();

      WebResponse web_response = http_web_request.GetResponse();
      string response_imp =
          new System.IO.StreamReader(web_response.GetResponseStream()).ReadToEnd();
    }
  }
}

出力:

[redirect the user to the `index.php` after a successful login]

* or

[shows an error for wrong username or password for invalid user]

ブラウザーを自動化するために Selenium サーバーは必要ありません。 ネイティブ OS レベルのイベントを使用して JavaScript サンドボックスをバイパスし、ブラウザーを操作します。

さらに、簡潔でオブジェクトベースの Selenium WebDriver API の .NET バインディングが含まれています。

Selenium にはさまざまなソフトウェア ツールがバンドルされており、それぞれがブラウザーの自動化をサポートするためのアプローチが異なります。 ブラウザー内の要素を見つけて操作するための非常に柔軟なツールを提供し、複数のブラウザー プラットフォームの自動化をサポートします。

C#HttpClient を使用して Web サイトにログインする

リダイレクトのステータス コードは 3** であるため、実際のログイン応答にアクセスするのに役立ちます。 HttpClient でリダイレクトを無効にする必要があります。 HTTP 動詞 リクエスト メソッドを使用して URL をリクエストするための資格情報を送信します (または、ほとんどの場合、POST メソッドを使用できます)。

サーバーがログインしたユーザーから受け取ることを期待する Cookie に基づいてログイン メソッドを実装することは常に簡単です。この情報は set-cookie ヘッダーに含まれるデータに基づいています。

GET には HTTP 本体が含まれていないため、HttpClientGET および POST メソッドを使用して Web サイトにログインできます。 POST を使用すると、データは QueryString から HTTP 本体に移動します。

ユーザー資格情報または渡すデータはパラメーターを介して渡され、残りはハードコーディングされます。 最も重要なことは、キーと値のペアのインスタンス (KeyValuePair<string, string>) が、プログラムで Web サイトにログインするのに役立つフォーム データの指定されたシーケンスを表すことです。

場合によっては、ユーザーが指定したデータのみが必要になることがあります。Web サイトでログイン ページの非表示フィールドを含める必要がある場合は、Web サイトを要求し、AngleSharp または同様の方法を使用して HTML を解析することが不可欠な手順です。

結論として、キーと値 (null 許容文字列) を含む結果のシーケンスが FormUrlEncodedContent コンストラクターに渡されます (シーケンスのキーと値が null 許容文字列であることが想定されます)。

// try not to change the entry point of this C# code
// it's important to remember that the `website_login.Program.Main` in your C# project is the entry
// point of this C# program. changing the entry point can lead to many difficulties and logical or
// syntax errors

using System;
using System.Net;
using System.IO;

namespace website_login {
  public class Program {
    public static void Main(string[] args) {
      var add_primary = new Uri("https://www.example_website.com/");
      var container_cookie = new CookieContainer();  // for web request

      // generate a proper web request | special HTTP implementation of the `WebRequest` class
      HttpWebRequest post_request_web =
          (HttpWebRequest)HttpWebRequest.Create("https://www.example_website.com/");
      post_request_web.CookieContainer = container_cookie;

      /*
       * setting the agent (user_agent) and accepting the header values
       * these are important to simulate a real web browser
       */
      post_request_web.UserAgent =
          "Chrome/5.3 (Windows Professional 11.2; WOW32) Chrome/45.0.2454.101";  // change it with
                                                                                 // respect to your
                                                                                 // platform, OS,
                                                                                 // and browser
      post_request_web.Accept =
          "text_type/html,c_sharp_application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";  // set values

      Console.WriteLine("[response from the server...]");
      Console.WriteLine();

      // generate a proper web response
      using (WebResponse get_response_web = post_request_web.GetResponse()) {
        // to read the response from the web server
        using (StreamReader stream_reader =
                   new StreamReader(get_response_web.GetResponseStream())) {
          Console.WriteLine(stream_reader.ReadToEnd());  // display
        }
      }

      post_request_web = (HttpWebRequest)HttpWebRequest.Create("https://www.example_website.com/");

      // setting `container_cookie` as a cookie container object
      post_request_web.CookieContainer = container_cookie;

      post_request_web.UserAgent =
          "Chrome/5.3 (Windows Professional 11.2; WOW32) Chrome/45.0.2454.101";  // change it with
                                                                                 // respect to your
                                                                                 // platform, OS,
                                                                                 // and browser
      post_request_web.Accept =
          "text_type/html,c_sharp_application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";  // set values

      post_request_web.Method = "POST";  // POST method because of web request
      post_request_web.ContentType =
          "application/x-www-form-urlencoded";  // it is a standard content type

      // the `user_infomration` variable contains the username and password of a user for login
      string user_information =
          string.Format("username={0}&password={1}", "your_username", "your_password");

      // encode the user information to send it to the web server
      byte[] _web_bytes = System.Text.Encoding.UTF8.GetBytes(user_information);

      post_request_web.ContentLength = _web_bytes.Length;

      using (Stream web_stream_user_info = post_request_web.GetRequestStream()) {
        web_stream_user_info.Write(_web_bytes, 0, _web_bytes.Length);
        web_stream_user_info.Close();
      }

      Console.WriteLine("[response form the server on user login...]");
      Console.WriteLine();

      using (WebResponse web_response_dll = post_request_web.GetResponse()) {
        // to read the response from the web server
        using (StreamReader stream_reader_dll =
                   new StreamReader(web_response_dll.GetResponseStream())) {
          Console.WriteLine(stream_reader_dll.ReadToEnd());  // display
        }
      }

      //....
    }
  }
}

出力:

[response from the server...]

... // some response from the website
*response from the `streamreader`*

[response from the server on user login...]
// response from the server or website after the first login attempt

FormUrlEncodedContent コンストラクターのインスタンスは、PostAsync 呼び出しの POST 要求の主要なコンテンツです。この呼び出しを行った後の次のステップは、HTTP 応答から set-cookie ヘッダーを解析することです。 .NET クラス ライブラリで適切な NuGet パッケージを見つけるのは常に難しい選択です。そのため、正規表現を使用して解析する方が優れた方法です。

応答 Cookie をチェックしてログインの失敗を検出するか、サーバーからの応答のステータス コードをチェックするか、サーバーから返された HTML コンテンツを解析します。 要求されたページをダウンロードする前に LoginAsync を呼び出すことは、サーバーへの要求に使用するログイン Cookie を取得または返すための優れたオプションです。

組み込みの GetStringAsync メソッドのオーバーロードに Cookie のパラメーターが含まれていない場合は、拡張メソッドを自分で作成します。次の C# コードでその作成を確認できます。 SendAsync メソッドを使用して要求 (生成された HTTP 要求) を送信する前に、すべての Cookie を単一の cookie ヘッダーに結合する必要があります。

ログイン応答ステータス コードでリダイレクトが必要な場合に、HttpClient の自動リダイレクト機能を無効にする場合のオプションです。 これは、HttpClient インスタンスを使用して行うことができます。依存性注入のために HttpClient を登録するときにオプションを渡すことにより、IHttpClientFactory でこれを行うことができるからです。

HttpClient または .NET には組み込み機能がないため、一般に、プログラムで Web サイトにログインするには、すべての手順を手動で実行する必要があり、毎回プロセスが異なる可能性があります。 認証またはログイン データは Cookie に設定されるため、CookieContainer を設定して、HttpClient を使用して標準の FormsAuthentication Web サイトでログインを実行します。

Syed Hassan Sabeeh Kazmi avatar Syed Hassan Sabeeh Kazmi avatar

Hassan is a Software Engineer with a well-developed set of programming skills. He uses his knowledge and writing capabilities to produce interesting-to-read technical articles.

GitHub

関連記事 - Csharp Authentication