web-dev-qa-db-ja.com

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

私はC#を使用するのは比較的新しく、Webサイト上のソースコードの一部を読み取るアプリケーションを使用しています。それはすべて機能します。問題は、問題のページがこのソースコードにアクセスするためにユーザーのログインを要求することです。私のプログラムが最初にユーザーをWebサイトにログインする方法に必要なもの-それが完了したら、ソースコードにアクセスして読み取ることができるようになります。

ログインする必要があるWebサイトは、mmoinn.com/index.do?PageModule = UsersLoginです。

私はこれを行う方法について一日中検索し、例を試しましたが、運がありませんでした。

前もって感謝します

70
Dillon

WebClientを引き続き使用してPOST(GETの代わりに HTTP動詞 DownloadStringで現在使用しています)が、あなたはそれを見つけると思います(わずかに)下位レベルのクラスWebRequestおよびWebResponseでの作業が簡単になりました。

これには2つの部分があります。1つ目はログインフォームを送信すること、2つ目は「Set-cookie」ヘッダーを回復し、GETリクエストとともに「Cookie」としてサーバーに送り返すことです。サーバーはこのCookieを使用してこれからユーザーを識別します(Cookieベースの認証を使用していると仮定します。このページは "PHPSESSID"を含むSet-cookieヘッダーを返すため、かなり確信しています)。


ログインフォームへの投稿

フォームの投稿は簡単にシミュレートできます。投稿データを次のようにフォーマットするだけです。

field1=value1&field2=value2

Scott Hanselman から適応したWebRequestとコードを使用して、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に保持されている文字列を調べます。

103
Matt Brindley

WebClientから派生するクラスを作成し、そのGetWebRequestメソッドをオーバーライドし、それにCookieContainerオブジェクトを設定することにより、物事をかなり簡素化できます。常に同じCookieContainerインスタンスを設定する場合、Cookie管理は自動的に処理されます。

ただし、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");
34
Josh

場合によっては、AllowAutoRedirectをオフにして、ログインPOSTとページGETの両方を設定すると、同じユーザーエージェントが要求される場合があります。

request.UserAgent = userAgent;
request.AllowAutoRedirect = false;
2
TN.