C #을 통해 웹 사이트에 로그인


81

저는 비교적 C #을 처음 사용하고 웹 사이트에서 소스 코드의 일부를 읽는 애플리케이션이 있습니다. 모두 작동합니다. 그러나 문제는 문제의 페이지에서 사용자가이 소스 코드에 액세스하기 위해 로그인해야한다는 것입니다. 내 프로그램에 웹 사이트에 사용자를 처음 로그인하는 방법이 필요한 것은이 작업이 완료되면 소스 코드에 액세스하여 읽을 수 있습니다.

로그인해야하는 웹 사이트 : mmoinn.com/index.do?PageModule=UsersLogin

이 작업을 수행하는 방법에 대해 하루 종일 검색하고 예제를 시도했지만 운이 없었습니다.

미리 감사드립니다


그래서 저는 이것을하기위한 여러 가지 방법을 생각할 수 있습니다 ... C # 프로그램이 HTTP를 통해 서버에서 직접 '코드'를 요청합니까, 아니면 브라우저 애플리케이션에 피기 백합니까? 더 많은 정보가 필요합니다.
Mitch Baker

이 프로그램은 WebClient.DownloadString ( "URL")을 사용합니다

답변:


112

( 현재 DownloadString과 함께 사용중인 HTTP 동사 인 GET 대신) WebClient를 POST에 계속 사용할 수 있지만 (약간) 하위 수준 클래스 WebRequest 및 WebResponse로 작업하는 것이 더 쉬울 것이라고 생각합니다.

여기에는 두 부분이 있습니다. 첫 번째는 로그인 양식을 게시하는 것이고 두 번째는 "Set-cookie"헤더를 복구하여 GET 요청과 함께 "쿠키"로 서버에 다시 보내는 것입니다. 서버는 지금부터 귀하를 식별하기 위해이 쿠키를 사용할 것입니다 (이 페이지가 "PHPSESSID"를 포함하는 Set-cookie 헤더를 반환하므로 쿠키 기반 인증을 사용한다고 가정합니다).


로그인 양식에 게시

양식 게시물은 시뮬레이션하기 쉬우 며 다음과 같이 게시물 데이터 형식을 지정하는 경우 일뿐입니다.

field1=value1&field2=value2

WebRequest 및 Scott Hanselman 에서 수정 한 코드를 사용하여 양식 데이터를 로그인 양식에 POST하는 방법은 다음과 같습니다.

string formUrl = "http://www.mmoinn.com/index.do?PageModule=UsersAction&Action=UsersLogin"; // NOTE: This is the URL the form POSTs to, not the URL of the form (you can find this in the "action" attribute of the HTML's form tag
string formParams = string.Format("email_address={0}&password={1}", "your email", "your password");
string cookieHeader;
WebRequest req = WebRequest.Create(formUrl);
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(formParams);
req.ContentLength = bytes.Length;
using (Stream os = req.GetRequestStream())
{
    os.Write(bytes, 0, bytes.Length);
}
WebResponse resp = req.GetResponse();
cookieHeader = resp.Headers["Set-cookie"];

다음은 로그인 양식의 Set-cookie 헤더에 표시되어야하는 내용의 예입니다.

PHPSESSID=c4812cffcf2c45e0357a5a93c137642e; path=/; domain=.mmoinn.com,wowmine_referer=directenter; path=/; domain=.mmoinn.com,lang=en; path=/;domain=.mmoinn.com,adt_usertype=other,adt_host=-

로그인 양식 뒤에있는 페이지 가져 오기

이제 로그인해야하는 페이지에 대한 GET 요청을 수행 할 수 있습니다.

string pageSource;
string getUrl = "the url of the page behind the login";
WebRequest getRequest = WebRequest.Create(getUrl);
getRequest.Headers.Add("Cookie", cookieHeader);
WebResponse getResponse = getRequest.GetResponse();
using (StreamReader sr = new StreamReader(getResponse.GetResponseStream()))
{
    pageSource = sr.ReadToEnd();
}

편집하다:

첫 번째 POST의 결과를 확인해야하는 경우 반환 된 HTML을 다음과 같이 복구 할 수 있습니다.

using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
    pageSource = sr.ReadToEnd();
}

바로 아래 cookieHeader = resp.Headers["Set-cookie"];에 배치 한 다음 pageSource에있는 문자열을 검사하십시오.


자세한 답변에 감사드립니다. 하지만 아직 확실하지 않은 부분이 하나 있습니다. 게시 한 "쿠키 설정", "쿠키"또는 "PHPSESSID"와 관련된 내용을 변경해야합니까? 내 정보를 입력하는 프로그램에서 해당 코드를 사용하려고 시도했지만 로그인하지 않는 것 같습니다 (쿠키로 무언가를 망치고 있다고 가정합니다).

그대로 사용하려면 코드가 괜찮아 야합니다. 서버는 쿠키를 설정하고 (Set-cookie에서) 클라이언트 (귀하)는 쿠키를 쿠키로 백업합니다. 가장 먼저 확인해야 할 것은 첫 번째 POST가 실제로 사용자를 로그인한다는 것입니다. 서버가 POST 양식에서 다른 필드를 예상 한 것을 발견 할 수 있습니다 (이상하게 들리 겠지만 때때로 버튼 이름이있는 빈 필드가 필요함). POST 결과를 보는 방법을 보여주기 위해 게시물을 업데이트했습니다.
Matt Brindley

처음에 내가 뭘 잘못했는지 잘 모르겠지만 지금은 작동합니다! 도움을 주셔서 감사합니다.

1
사용자가 성공적으로 인증되었는지 어떻게 확인할 수 있습니까?
Cyral

2
여기에 감사를 표시해서는 안된다는 건 알지만 당신이 내 엉덩이를 구해 줬어요! +1
Owen James

39

WebClient에서 파생되는 클래스를 만들고 GetWebRequest 메서드를 재정의하고 CookieContainer 개체를 설정하여 작업을 상당히 단순화 할 수 있습니다. 항상 동일한 CookieContainer 인스턴스를 설정하면 쿠키 관리가 자동으로 처리됩니다.

그러나 HttpWebRequest가 전송되기 전에 얻을 수있는 유일한 방법은 WebClient에서 상속하고 해당 메서드를 재정의하는 것입니다.

public class CookieAwareWebClient : WebClient
{
    private CookieContainer cookie = new CookieContainer();

    protected override WebRequest GetWebRequest(Uri address)
    {
        WebRequest request = base.GetWebRequest(address);
        if (request is HttpWebRequest)
        {
            (request as HttpWebRequest).CookieContainer = cookie;
        }
        return request;
    }
}

var client = new CookieAwareWebClient();
client.BaseAddress = @"https://www.site.com/any/base/url/";
var loginData = new NameValueCollection();
loginData.Add("login", "YourLogin");
loginData.Add("password", "YourPassword");
client.UploadValues("login.php", "POST", loginData);

//Now you are logged in and can request pages    
string htmlSource = client.DownloadString("index.php");

디버깅 할 때 (공개로 만든) 쿠키는 항상 비어 있습니다. 웹 사이트는 확실히 다운로드 페이지에 쿠키를 제공하고 있습니다.
C4d

감사합니다. 몇 시간 동안 솔루션을 찾은 후에 작동합니다!
Essej

9

Matthew Brindley , 귀하의 코드는 내가 필요로하는 일부 웹 사이트 (로그인 포함)에서 매우 잘 작동했지만 변경해야 HttpWebRequest하고 HttpWebResponse그렇지 않으면 원격 서버에서 404 Bad Request를 받습니다. 또한 난 당신의 코드를 사용하여 내 해결 방법을 공유하고, 그리고 난에 로그인을 시도한다는 것이다 것이 무에 따라 웹 사이트 "하지만 당신의 단계에서 작동하지 않았다 로그인 폼 뒤에 페이지를 받고 성공적으로 할 때 때문에" 게시 을 로그인하면 'Set-Cookie'다른 웹 사이트에도 불구하고 헤더 가 아무것도 반환하지 않았습니다.

그래서 다음 요청을 위해 쿠키를 저장해야 할 곳이라고 생각하여 이것을 추가했습니다.


" POSTing to the login form "코드 블록 :

var cookies = new CookieContainer();
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(formUrl);
req.CookieContainer = cookies;


그리고 " 로그인 양식 뒤에 페이지 가져 오기 ":

HttpWebRequest getRequest = (HttpWebRequest)WebRequest.Create(getUrl);
getRequest.CookieContainer = new CookieContainer();
getRequest.CookieContainer.Add(resp.Cookies);
getRequest.Headers.Add("Cookie", cookieHeader);


이렇게하면 로그인 하여 "로그인 페이지"(웹 사이트 기반 무들)의 소스 코드를 얻을 CookieContainer수 있습니다. 먼저 이전에 저장된 쿠키 세트가 있는지 먼저 물어볼 수 있기 때문에 이것이 및 HTTPCookies 의 모호한 사용이라는 것을 알고 있습니다. 서버에 요청을 보냅니다. 문제없이이 작품 어쨌든, 그러나 여기에 대해 읽을 수있는 좋은 정보입니다 WebRequestWebResponse: 튜토리얼 샘플 프로젝트와 함께
도서관을 찾는 중 HTTP 콘텐츠 .NET
.NET에서 사용하는 방법을 HttpWebRequest와 HttpWebResponse 클래스는


2

때로는 동일한 사용자 에이전트를 끄고 AllowAutoRedirect로그인 POST및 페이지 GET요청을 모두 설정하는 데 도움이 될 수 있습니다 .

request.UserAgent = userAgent;
request.AllowAutoRedirect = false;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.