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


81

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

ログインする必要のあるWebサイトは次のとおりです。mmoinn.com/ index.do?PageModule = UsersLogin

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

前もって感謝します


だから、私はこれを行うためのたくさんの方法を考えることができます... C#プログラムはHTTP経由でサーバーから直接「コード」を要求しますか、それともブラウザアプリケーションに便乗しますか?もう少し情報が必要です。
ミッチベイカー

プログラムはWebClient.DownloadString( "URL")を使用します

回答:


113

(現在DownloadStringで使用しているHTTP動詞であるGETの代わりに)WebClientを引き続きPOSTに使用できますが、(わずかに)低レベルのクラスWebRequestおよびWebResponseを使用する方が簡単だと思います。

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


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

フォームの投稿は簡単にシミュレートできます。これは、投稿データを次のようにフォーマットする場合にすぎません。

field1=value1&field2=value2

WebRequestクラスと私はから適応コード使用スコット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に保持されている文字列を調べます。


詳細な回答をありがとうございました。しかし、私が確信していない部分がまだ1つあります。あなたが投稿した「Set-cookie」、「Cookie」、または「PHPSESSID」に関して何かを変更することになっていますか?情報を入力してプログラムでそのコードを使用しようとしましたが、ログインしていないようです(Cookieで何かを台無しにしていると思います)。

コードは逐語的に使用しても問題ないはずです。サーバーはCookieを(Set-cookieで)設定し、クライアント(つまりあなた)はCookieをCookieとして送り返します。最初に確認することは、最初のPOSTが実際にログインしていることです。サーバーが、フォームPOSTに別のフィールドを予期していることがあります(奇妙なことに、ボタンの名前が付いた空のフィールドが必要になる場合があります)。POSTの結果を表示する方法を示すために投稿を更新しました。
Matt Brindley

初めて何を間違えたのかわかりませんが、今はうまくいきます!助けてくれてありがとう。

1
ユーザーが正常に認証されたかどうかを確認するにはどうすればよいですか?
Cyral 2012年

2
私たちはここに感謝することになっていないことを知っていますが、あなたが私のお尻を救った男!+1
オーウェンジェームス

39

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");

デバッグ時には、(公開された)Cookieは常に空です。ウェブサイトは確かに私がダウンロードしているページでクッキーを配っています。
c4d 2016年

おかげで、解決策を見つけるのに数時間後、これはうまくいきます!
essej 2017年

9

Matthew Brindley、あなたのコードは私が必要としたいくつかのウェブサイト(ログインあり)では非常にうまく機能しましたが、に変更する必要がHttpWebRequestありました。HttpWebResponseそうしないと、リモートサーバーから404 BadRequestを受け取ります。また、あなたのコードを使用して回避策を共有したいと思います。moodleに基づいてウェブサイトにログインしようとしましたが、「ログインフォームの後ろのページを取得する」のステップでうまくいきませんでした。ログインすると、'Set-Cookie'他のWebサイトが返すにもかかわらず、ヘッダーは何も返しませんでした。

したがって、次のリクエストのためにCookieを保存する必要がある場所だと思うので、これを追加しました。


ログインフォームへのPOST」コードブロックへ:

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);


これをやって、私がすることができますで私のログ、私はこれは漠然と使用である知っていて、「ログイン背後ページ」(ウェブサイトベースのmoodle)のソースコードを取得しCookieContainer、我々は最初に求めることができるので、とHTTPCookies以前に前に保存したクッキーのセットがありますサーバーにリクエストを送信します。これはとにかく問題なく動作しますがWebRequestWebResponseサンプルプロジェクトとチュートリアルについて読むための良い情報があります:
.NETでのHTTPコンテンツの取得.NETでの
HttpWebRequestとHttpWebResponseの使用方法


2

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

request.UserAgent = userAgent;
request.AllowAutoRedirect = false;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.