C#에서 웹사이트에 로그인

Syed Hassan Sabeeh Kazmi 2023년10월12일
  1. WebClient를 사용하여 C#의 웹사이트에 로그인
  2. C#에서 웹사이트에 로그인하는 스크립트 작성
  3. C#에서 Selenium을 자동화하여 웹 사이트에 로그인하는 스크립트 만들기
  4. HttpClient를 사용하여 C#의 웹사이트에 로그인
C#에서 웹사이트에 로그인

이 자습서에서는 C#에서 프로그래밍 방식으로 웹 사이트에 로그인하는 최적화된 방법을 배우고 이해합니다. ASP.NET C#을 사용하여 외부 웹사이트에 자동 로그인이 가능하며, 웹사이트에서 로그인 확인을 위해 HTTP POST를 사용하는 경우 외부에서 post 메소드를 사용할 수 있습니다.

Visual Studio에서 프록시 클래스 웹 서버 메서드를 호출하여 자동으로 프록시를 생성하므로 C# 프로젝트에 서비스 참조를 추가하는 일반적인 방법입니다. 그러나 프로그래밍 방식은 웹 서버를 호출하고 인증하는 완벽한 방법입니다.

WebClient를 사용하여 C#의 웹사이트에 로그인

웹사이트에 프로그래밍 방식으로 로그인하는 가장 좋은 방법은 WebClientPOST에 사용하는 것입니다. POST(엔트리 레벨 개발자에게는 매우 복잡하기 때문에)의 확실한 대체품은 하위 레벨 WebRequestWebResponse 클래스입니다.

로그인 양식을 만드는 것은 이 접근 방식의 두 가지 기본 부분 중 하나이며 두 번째는 GET 요청을 사용하여 Set-cookie 헤더를 복구하는 것입니다. GET 요청과 함께 보낸 CookieSet-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를 사용하여 웹 사이트에 로그인하는 Scott Hanselman 접근 방식을 반영합니다.

또한 다음 C# 코드는 프로그래밍 방식으로 웹 사이트에 로그인하기 위해 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를 사용하여 웹사이트에 로그인할 수 있는 C# 코드입니다. 그러나 자신의 사용자 이름과 암호를 사용하고 웹사이트 URL을 입력해야 하며 로그인 성공 후 C# 프로그램이 리디렉션할 웹페이지를 언급하는 것을 잊지 마십시오.

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]

또 다른 흥미로운 아이디어는 WebClient에서 파생되는 클래스를 생성하여 재정의한 후 GetWebRequest 메서드에 CookieContainer 개체를 설정하여 이 접근 방식을 수정하는 것입니다. 단일 또는 동일한 CookieContainer 인스턴스는 기본적으로 쿠키 관리를 처리할 수 있습니다.

C#에서 웹사이트에 로그인하는 스크립트 작성

프로그래밍 방식으로 웹사이트에 로그인하는 것은 웹사이트가 로그인 절차를 구현하는 방식과 밀접하게 연결되어 있기 때문에 각 웹사이트의 로그인 절차는 고유할 수 있으며 다른 프로토콜이 필요합니다. 프로세스를 이해하고 이에 따라 요청 및 응답(서버에서 송수신)을 작성해야 합니다.

웹 사이트의 절차를 통과하기 위해 엄청나게 복잡하고 깨지기 쉬운 스크립트를 작성하는 것은 쉬운 일이 아니지만 그렇게 하면 응용 프로그램의 보안과 효율성을 향상시킬 수 있습니다. 또한 다음과 같이 AllowAutoRedirect를 끄고 POSTGET 요청을 동일한 사용자 에이전트에 설정하는 데 도움이 될 수 있습니다.

request.UserAgent = UserAgent;

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

일부 웹사이트는 로그인을 시도할 때 암호화된 URL로 인코딩된 반환 값을 전송하며, 서버에서 무언가 빠진 것을 발견하면 HTTP/1.1 400 잘못된 요청과 같은 메시지를 표시하거나 서버에서 내부 어딘가에 묻혀있는 오류 메시지. 올바른 값을 수집하고 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을 자동화하여 웹 사이트에 로그인하는 스크립트 만들기

수동 스크립트를 작성하는 것이 어려울 수 있으므로 selenium.WebDriver를 자동화하는 스크립트를 만드는 것은 C#에서 프로그래밍 방식으로 웹 사이트에 로그인하는 유효한 옵션이 될 수 있습니다. 유효한 쿠키를 꺼낼 수 있도록 모든 저글링을 처리하여 정상적으로 요청을 던질 수 있습니다.

코드를 최적화하려면 셀레늄을 이해하는 것이 중요합니다. 예를 들어 azure에 로그인하여 스크립트 작성을 매우 짧게 만드는 크레딧을 얻는 데 효과적입니다. 그러나 CookieContainer exp_cookie = new CookieContainer();가 없기 때문에 이는 CookieContainer를 지원하는 웹사이트에 적합하지 않음을 의미합니다.

// 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은 브라우저 자동화를 지원하는 서로 다른 접근 방식을 가진 다양한 소프트웨어 도구 번들을 제공합니다. 브라우저 내에서 요소를 찾고 조작하기 위한 매우 유연한 도구를 제공하고 여러 브라우저 플랫폼에 대한 자동화를 지원합니다.

HttpClient를 사용하여 C#의 웹사이트에 로그인

리디렉션에 대한 상태 코드가 3**이므로 실제 로그인 응답에 액세스하는 데 도움이 될 수 있습니다. HttpClient로 리디렉션을 비활성화해야 합니다. HTTP 동사 요청 방법(또는 대부분의 경우 POST 방법일 수 있음)을 사용하여 URL을 요청하기 위해 자격 증명을 보냅니다.

서버가 로그인한 사용자로부터 받을 것으로 예상하는 쿠키를 기반으로 로그인 방법을 구현하는 것은 항상 쉽습니다. 이 정보는 set-cookie 헤더에 포함된 데이터를 기반으로 합니다.

GET에는 HTTP 본문이 포함되어 있지 않으므로 HttpClient에서 GETPOST 메서드를 사용하여 웹 사이트에 로그인할 수 있습니다. POST를 사용하면 데이터가 QueryString에서 HTTP 본문으로 이동합니다.

전달할 사용자 자격 증명 또는 데이터는 매개 변수를 통해 전달되며 나머지는 하드 코딩됩니다. 가장 중요한 것은 키-값 쌍 인스턴스(KeyValuePair<string, string>)가 프로그래밍 방식으로 웹 사이트에 로그인하는 데 도움이 되는 지정된 양식 데이터 시퀀스를 나타냅니다.

경우에 따라 사용자 지정 데이터만 필요한 경우가 발생할 수 있으며 웹사이트에서 로그인 페이지의 숨겨진 필드를 포함하도록 요구하는 경우 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 패키지를 찾는 것은 항상 어려운 선택이므로 정규식을 사용하여 구문 분석하는 것이 더 좋은 방법입니다.

응답 쿠키를 확인하여 실패한 로그인을 감지하거나, 서버에서 응답의 상태 코드를 확인하거나, 서버에서 반환된 HTML 콘텐츠를 구문 분석합니다. 요청된 페이지를 다운로드하기 전에 LoginAsync를 호출하는 것은 항상 서버 요청에 사용할 로그인 쿠키를 검색하거나 반환하는 훌륭한 옵션입니다.

쿠키에 대한 매개 변수가 있는 기본 제공 GetStringAsync 메서드 오버로드가 없으면 다음 C# 코드에서 해당 생성을 관찰할 수 있으므로 직접 확장 메서드를 만듭니다. 요청(생성된 HTTP 요청)을 보내기 위해 SendAsync 메서드를 사용하기 전에 모든 쿠키를 단일 cookie 헤더로 결합해야 합니다.

로그인 응답 상태 코드에 리디렉션이 필요한 경우 HttpClient의 자동 리디렉션 기능을 비활성화하려는 경우 옵션입니다. 종속성 주입을 위해 HttpClient를 등록할 때 옵션을 전달하여 IHttpClientFactory로 이 작업을 수행할 수 있으므로 HttpClient 인스턴스로 수행할 수 있습니다.

HttpClient 또는 .NET에는 일반적으로 내장된 기능이 없으므로 프로그래밍 방식으로 웹 사이트에 로그인하려면 모든 단계를 수동으로 수행해야 하며 매번 프로세스가 다를 수 있습니다. 인증 또는 로그인 데이터는 쿠키에 설정되므로 CookieContainer를 설정하여 HttpClient를 사용하여 표준 FormsAuthentication 웹 사이트에서 로그인을 수행합니다.

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