C#によるWEBサイトへのログイン方法(ベーシック認証、クッキー認証)

クライアントアプリからのWEBサイトへのログイン認証方法について調べてみました。

以下2タイプの認証方法について記載しています。
①ベーシック認証
 ブラウザでアクセスすると、IDとPASSの入力を促すダイアログが
 表示されるタイプのサイトへのログイン。

②クッキー認証(と呼ぶのが正しいかどうか不明です^^;)
 mixiとかニコニコ動画とか、フォームにメアドとパスワードを入力して
 ログインするタイプのサイトへのログイン。
 例として、ニコニコ動画へのログインアプリを作ってみました。
 


 

①ベーシック認証

ブラウザでアクセスすると、IDとパスワードの入力を促すダイアログが
表示されるタイプのサイトへのログイン方法です。

以下、WebCliantのDownloadDataメソッドによりサイトのHTMLをダウンロードするサンプルです。
Credentialsプロパティに認証情報を設定するだけでOKです。

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            WebClient myweb = new WebClient();
            //認証情報
            myweb.Credentials = new NetworkCredential("ユーザーID", "パスワード");

            //ダウンロード
            byte[] pagedata = myweb.DownloadData("http://hoge.com/認証が必要なサイトのURL/");
            //Encoding ec = Encoding.UTF8;

            //取得先のサイトに合わせた文字コード設定
            //Encoding ec = Encoding.UTF8;//UTF8の例
            Encoding ec = Encoding.GetEncoding("shift-jis");//シフトGISの例
            Console.WriteLine(ec.GetString(pagedata));
        }
    }

 
 
 


②クッキー認証(ニコニコ動画へのログインサンプル)

 mixiやニコニコ動画等、フォームにメアドとパスワードを入力してログインするタイプのサイトへのログインです。
 ログイン時にクッキーを取得し、以降そのサイトへのアクセスには取得したクッキーを用いて認証します。
 今回はニコニコ動画へログインする方法を記載します。

・ログインに必要な情報の調査

 事前にログインフォームを解析し、ログインに必要な情報を調査します。
 以下はニコニコ動画ログインページのHTMLです。

<form action="https://secure.nicovideo.jp/secure/login?site=niconico" method="post" onsubmit="if (tooAdvancedClock) alert('お使いの PC の時計が進みすぎているため、正常にログインができない場合がございます。');">
	<input type="hidden" name="next_url" value="">
	<dl>

		<dt><label for="mail">ログインメールアドレス</label></dt>
		<dd><input id="mail" name="mail" type="text" class="txt"></dd>
		<dt><label for="password">パスワード</label></dt>
		<dd>
			<input id="password" name="password" type="password" class="txt">
			<p class="forgetPass">※パスワードを忘れた方は<a href="https://secure.nicovideo.jp/secure/remind_pass">再発行の手続き</a>へ</p>

		</dd>
		<dd class="buttons">
			<div class="wrongPass"></div>
			<input type="submit" value="" class="submit">
		</dd>
	</dl>
</form>

 上記から以下のことが分かります。

・ログイン時アクセスすべきURLはhttps://secure.nicovideo.jp/secure/login?site=niconico
・必要なパラメタは、next_url、mail、passwordの3つ
・next_urlは空文字列””でよい

・ログインパラメタ作成

	        //ニコニコ動画ログイン用IDとPASSWORDを指定
            string id = "hoge@hoge.ne.jp";//メアド
            string password = "hogehoge";//パスワード

            //ログイン・ページへのアクセスパラメタ
            //ここで必要な情報は、ログインページのHTMLソースを見て、
            //"input"で検索して調べる
            Hashtable vals = new Hashtable();
            vals["next_url"]	= "";
            vals["mail"]		= id;
            vals["password"]	= password;
            //ログインボタンが押されたときにpostされるURL
            //これもログインページのHTMLを見て、formタグから調べる
            string url = "https://secure.nicovideo.jp/secure/login?site=niconico";

            //パラメタを"param1=value1&param2=value2"の形にまとめる
            string param = "";
            foreach (string k in vals.Keys)
            {
                param += String.Format("{0}={1}&", k, vals[k]);
            }
            byte[] data = Encoding.ASCII.GetBytes(param);

・POSTリクエスト発行

作成したパラメタを用いてPOSTリクエストを発行します。

            //HTTP POSTリクエストの作成
            CookieContainer cc = new CookieContainer(); //認証用クッキーを格納するコンテナ
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method			= "POST";
            req.ContentType		= "application/x-www-form-urlencoded";
            req.ContentLength	= data.Length;
            req.CookieContainer = cc;

            //POSTを実行
            Stream reqStream = req.GetRequestStream();
            reqStream.Write(data, 0, data.Length);
            reqStream.Close();

・レスポンス取得

認証後のHTMLソースが取得できます。

            //レスポンスの取得
            WebResponse res = req.GetResponse();
            Stream resStream = res.GetResponseStream();
            
            Encoding encoder = Encoding.GetEncoding("UTF-8");
            StreamReader sr = new StreamReader(resStream, encoder);
            string result = sr.ReadToEnd();
            sr.Close();
            resStream.Close();
            
            Console.WriteLine(result);//ログイン後のHTMLが取得されている

・以降のアクセス

以降は取得したクッキーを使用したGETリクエストによりアクセスできます。

			//以降はHTTP GETのみでアクセスできる
			//例として、ニコニコ動画のマイページにアクセスしてみる
            url = "http://www.nicovideo.jp/my/top";

            //HTTP GET リクエストの作成
            req = (HttpWebRequest)WebRequest.Create(url);
            req.CookieContainer = cc;//取得済みのクッキーコンテナ
            res = req.GetResponse();
            resStream = res.GetResponseStream();
            sr = new StreamReader(resStream, encoder);
            result = sr.ReadToEnd();
            sr.Close();
            resStream.Close();

            Console.WriteLine(result);//マイページのHTMLが取得されている

・ニコニコ動画ログインアプリのサンプル

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Collections;

namespace ConsoleApplication1
{
    public class Program
    {
        static void Main()
        {
	        //ニコニコ動画ログイン用IDとPASSWORDを指定
            string id = "hoge@hoge.ne.jp";//メアド
            string password = "hogehoge";//パスワード

            //ログイン・ページへのアクセスパラメタ
            //ここで必要な情報は、ログインページのHTMLソースを見て、
            //"input"で検索して調べる
            Hashtable vals = new Hashtable();
            vals["next_url"]	= "";
            vals["mail"]		= id;
            vals["password"]	= password;
            //ログインボタンが押されたときにpostされるURL
            //これもログインページのHTMLを見て、formタグから調べる
            string url = "https://secure.nicovideo.jp/secure/login?site=niconico";

            //パラメタを"param1=value1&param2=value2"の形にまとめる
            string param = "";
            foreach (string k in vals.Keys)
            {
                param += String.Format("{0}={1}&", k, vals[k]);
            }
            byte[] data = Encoding.ASCII.GetBytes(param);

            //HTTP POSTリクエストの作成
            CookieContainer cc = new CookieContainer(); //認証用クッキーを格納するコンテナ
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method			= "POST";
            req.ContentType		= "application/x-www-form-urlencoded";
            req.ContentLength	= data.Length;
            req.CookieContainer = cc;

            //POSTを実行
            Stream reqStream = req.GetRequestStream();
            reqStream.Write(data, 0, data.Length);
            reqStream.Close();

			//レスポンス取得
            WebResponse res = req.GetResponse();
            Stream resStream = res.GetResponseStream();
            
            Encoding encoder = Encoding.GetEncoding("UTF-8");
            StreamReader sr = new StreamReader(resStream, encoder);
            string result = sr.ReadToEnd();
            sr.Close();
            resStream.Close();
            
            Console.WriteLine(result);//ログイン後のHTMLが取得されている


			//以降はHTTP GETのみでアクセスできる
			//例として、ニコニコ動画のマイページにアクセスしてみる
            url = "http://www.nicovideo.jp/my/top";

            //HTTP GET リクエストの作成
            req = (HttpWebRequest)WebRequest.Create(url);
            req.CookieContainer = cc;//取得済みのクッキーコンテナ
            res = req.GetResponse();
            resStream = res.GetResponseStream();
            sr = new StreamReader(resStream, encoder);
            result = sr.ReadToEnd();
            sr.Close();
            resStream.Close();

            Console.WriteLine(result);//マイページのHTMLが取得されている
        }
    }
}

参考:http://www.atmarkit.co.jp/fdotnet/dotnettips/326cookie/cookie.html

41件のコメント

  1. mixiから
    C#については、全く知らなかったので参考になりました(^^
    こんな面白いことできるんですね。
    自分もさっそく試してみます(^^

  2. ロフトくん

    面白いと感じて頂けて( ̄ー ̄)ニヤリです。
    ニコニコ動画には情報取得用のWEB APIも存在するそうですよ。

  3. ピンバック:HTTP POST/GET クッキー認証によるWebサイトへのログイン (Android, Java) « 夏研ブログ

  4. ちょうど似たようなことをやろうと思って探していましたので、参考になりました!

  5. ロフトくん

    >じゃがさん
    こんにちは。閲覧&コメントありがとうございます。
    参考になりましたら幸いです。

  6. 感動しました。
    まさに私が求めていたコードです。

  7. メモ2  Tips (4) HTMLを解析する  http://t.co/xV81fXjK

  8. ロフトくん

    >bringerさん
    こんにちは。ありがとうございます!

  9. このような知識はどうやって手に入れてるんですか?
    書籍とかないでしょうか?

  10. ロフトくん

    >名無しさん
    こんにちは。
    若干古い書籍ですが『C#ではじめるWebサービスプログラミング』という書籍で、ほぼ予備知識ない状態から基礎を身につけました。
    (“お天気Webサービスから天気予報を取得”を実践。途中XMLの章はめんどいので流し読み。)

    “HTTP GET” “HTTP POST”ができるようになれば、以下のようなWebサービスについて、技術者向けに公開されている仕様を読んで利用できるようになります。
    ・Yahooの各種APIの利用(XMLを解析して情報を取得)
     知恵袋API、テキスト解析API etc
    ・RSSを取得(RSS=XML)
     ブログ更新情報、ニコ動ランキング、ニコ生番組表 etc
    ・2chのスレッドデータを取得
    ・HTMLを取得
     Webサービスが公開されていない場合はHTMLを自力で解析

    認証が必要なサービスの場合、ベーシック認証・クッキー認証なら当ブログ記事のような方法で比較的簡単に実装できます。
    Twitter等が採用しているOAuth認証は実装するのは大変なので、フリーで公開されているライブラリを使います。
    ご参考 http://c-loft.com/blog/?p=2007

    ここまではサーバが提供しているサービスを利用する側(=クライアント視点)の知識についてでした。

    クライアントからのHTTP GETやPOSTの要求を受けて処理する側(=サーバ側)の処理についてはPHPがとっつきやすいです。
    (他 Javaサーブレット、ASP(.NET)などもあるけどPHPが遥かに手軽、Rubyも人気だがまず始めるにはPHPだと思う。)

    サーバは自宅サーバを立ててもよいですがセキュリティや電気代が気になるので、月ワンコインくらいのレンタルサーバもおすすめです。

    PHPについてはWebに情報がたくさんあるので、そこでまかなえます。
    いきなり分厚い本を準備する必要はありません。
    以下の様なオリジナルのWebサービスを作れるようになります。
    ・アンテナサイト
     各種サイトのRSSを取得して見やすく整形・ソートして表示
     ブログ更新情報やニコニコのランキングなど。
    http://c-loft.com/blog/?p=598
    ・Twitter bot
     取得した情報を定期的につぶやく
    http://c-loft.com/blog/?p=2048

  11. 検索で、このページを見つけました。
    私もいちから勉強中なので、書籍の紹介は感謝します。
    早速注文しました。
    ありがとうございました。

  12. ロフトくん

    >283chocolatさん
    こんにちは。書籍がお役に立ちましたら幸いです。

  13. PHPとC#さえ学べばすごいソフトウエアが作れますね

  14. 通りすがり

    C#でWebサービスを利用する方法や必要知識をネット検索していたところ、ここへたどり着いたのが一か月前でした。
    コメント欄で紹介されていた書籍をすぐに購入して読了することが出来ました。
    4,5,6,7章はすでにサービスが終了していたりAPIの変更等でまともに動くものはありませんでしたが、3章XMLまで繰り返しMSDNと一緒に勉強しました。
    おかげでAmazonやその他、公開されているAPIへのリクエスト、レスポンスXMLを解析など出来るようになりました。C#でここまで体系的にWEBサービスについて説明されている書籍は他にはなかったと思います。
    ブログ主様には本当に感謝しております。
    長文失礼いたしました。

  15. ロフトくん

    >通りすがりさん
    こんにちは。
    紹介してよかったです。やはり良書であると確信しました^^
    現在のWebAPIに対応した続編が出ると良いのですが。。
    そもそも何から手をつけてよいかわからない状態から、あんなWebサービスやこんなWebサービスを利用するプログラムができるようになるまでひっぱってくれる良書ですよね。
    この本を読むと、書籍に載っていないWebサービスでもAPIドキュメントを読んで利用できるようになるので、最初に取っ掛かりとして読む本としてベストだと思います。

  16. はてなっち

    現在のニコニコ動画はフォームが変わっているようですが、
    この手法は通用するのでしょうか?

    この記事を参考にして
    msxml2.xmlhttpを使ってhttpリクエストしているのですが
    「お探しのページは見つかりませんでした。」とニコニコから返ってきます。

    post先は
    https://account.nicovideo.jp/login/api/v1/login?show_button_twitter=1&site=niconico&show_button_facebook=1

    パラメータは
    mail_tel、password、auth_idの3つです。

    クッキー付与の前にまずログインが出来ずに悩んでいます。
    post先とパラメータは前述の通りで良いのでしょうか?

    また、auth_idは可変するようですが
    どう対処すれば良いのでしょうか?

    よろしければご回答いただけると助かります。
    宜しくお願い致します。

  17. ロフトくん

    >はてなっちさん
    こんにちは。
    試してみたところ本ブログ記事のソースで現在でもログイン成功するようです。
    本ブログ記事の方法ではauth_idというパラメタは使用していません。
    雰囲気的にTwitterやFacebook等、SNSのアカウントでニコニコにログインする時のパラメタかもしれないですね。

  18. はてなっち

    ご返答ありがとうございます。
    今もまだ使えるコードだということで、
    問題の切り分けが進みました。

    ありがとうございます。
    1つ疑問なのですが
    https://account.nicovideo.jp/login
    現在のニコニコ動画はフォームは上記URLに変わりましたが
    現在のログインフォームのpost先を見るに

    【post先】
    https://account.nicovideo.jp/login/api/v1/login?show_button_twitter=1&site=niconico&show_button_facebook=1

    【パラメータ】
    mail_tel、password、auth_id

    だと思うのですが、
    これは合っているのでしょうか?

    >本ブログ記事の方法ではauth_idというパラメタは使用していません。
    >雰囲気的にTwitterやFacebook等、SNSのアカウントでニコニコにログインする時のパラメタかもしれないですね。

    とのことなので不思議に思っています。
    ご返答いただければ幸いです。

    • ロフトくん

      >はてなっちさん
      こんにちは。

      現在のログインフォームを見てみました。
      URL https://account.nicovideo.jp/login

      <form action="/api/v1/login?show_button_twitter=1&site=niconico&show_button_facebook=1" method="POST" id="login_form">
      

      上記より、
      POST先 https://account.nicovideo.jp/api/v1/login?show_button_twitter=1&site=niconico&show_button_facebook=1

          <input id="input__mailtel" type="text" name="mail_tel" value="">
          <input id="input__password" type="password" name="password">
      

      上記より
      パラメータはmail_telとpasswordの2つ。

      本ブログ記事のソースのurl変数とvals変数を上記に書き換えてログインできました。

      auth_idについては確かにJQueryで$(‘#login_form’)に追加するようなコードが書かれていますね。
      今回試してみた限りでは、パラメータにauth_idはなくてもログインできるようです。

      • ロフトくん

        追記:
        “雰囲気的にTwitterやFacebook等、SNSのアカウントでニコニコにログインする時のパラメタかもしれないですね。”は外れのようなので撤回します。

        JavaScriptが動作するブラウザからアクセスしたログインページに
        表示されるログインフォームには
        <form …id=”login_form”>~</form>間にauth_idパラメータが埋め込まれます。
        auth_idパラメータの値は/js/lib/fingerprint.js で計算されるようです。

        計算された値はクライアントPCの様々な環境情報を収集して数値化したもの(“指紋”)のようです。
        ご参考) http://qiita.com/okappy/items/5776054cb94f5bb83532

        ユーザーがそれぞれの”指紋”を送信することでニコニコサーバ側ではどんな環境からアクセスされたかを知れるようです。

  19. はてなっち

    ご返答ありがとうございます!

    ご対応本当にありがとうございますm(__)m
    formを直接解析+fiddlerで通信内容を確認していたのですが
    フォームの解析方法は間違っていなかったみたいで安心しました。

    >JQueryで$(‘#login_form’)に追加
    こちらはなぜJQueryを使っていると分かったのでしょうか?
    またauth_idで生成される値に/js/lib/fingerprint.jsが絡んでいると判断できた理由があれば教えていただきたいです。

    JQueryについては
    firefoxのfirebugでJQueryを解析してみましたが、
    JQuery内にlogin_formに関する記述が見当たりませんでした。
    今回直接ログインには関係ないようなので
    深追いしない方がいい問題なのかもしれませんが、

    POSTして色々やりたい時には
    まず解析が必要になってくると思うので
    こういった知識を少しでも多く身につけたいと思っているのですが、
    オススメの本などありますか?

    ※C#ではじめるWebサービスプログラミングは今日注文しました。

  20. ロフトくん

    >はてなっちさん
    こんにちは。
    URL https://account.nicovideo.jp/login のHTMLソースを見ますと、
    ログインformへのauth_idパラメタの追加処理が記述されています。
    記述内容:以下のような<input>タグをidがlogin_formの部品(form)の子要素として追加(append)する。
    ・隠し属性(hidden)である。 画面には入力フォームとして表示されないがパラメタはPOSTされる
    ・パラメタ名(name)はauth_idである。
    ・値(value)はFingerprint.get()の戻り値である。
    これはユーザが入力するのではなく、JavaScriptで計算された値である。
    ユーザはその存在も、値の意味も意識しない謎の値である。

    このJavaScriptコードはページがロードされた際の初期化処理として動作します。
    ( $(function() や $(‘#login_form’) はJQueryの文法です。
    <script src= タグを見ますと JQueryを記述できるよう、jquery-1.11.1.min.js が参照されています。 )

    また、new FingerPrint().get()を実行するにはFingerPrintクラスが定義されているjsファイルを参照しているはずなので、
    こちらも<script src= タグで fingerprint.js が参照されている事がわかります。

    fingerprint.jsの中を見ますと(そのままでは読みづらいですがChrome Developer Toolsのようなコード整形機能のあるツールですと読みやすくなります。)、
    確かにget()メソッドが実装されており、
    get()メソッド内にブレークポイントを張っておくと、確かにページロード時に動作していることが分かります。

    『C#ではじめるWebサービスプログラミング』 は、やや内容が古くなってしまっていますが、C#でHTTP GETやPOSTしたい場合の最初の本としておすすめです。
    これに替わる書籍は今のところ見つけていません(^^;)

    JavaScriptコードの動きやHTTP通信内容を解析するには(既に使われていらっしゃる)fiddlerや、firebugなど各ブラウザに付属のデバッガツールを活用されるのが良いと思います。

  21. はてなっち

    ご返答ありがとうございます。

    >これはユーザが入力するのではなく、JavaScriptで計算された値である。
    >ユーザはその存在も、値の意味も意識しない謎の値である。

    こういう思考で分析していってるのですね。
    そして、実際にブレークポイント張って確認して
    あたりをつけたということなのですね。

    javascript、JQUERYはほとんど勉強してこなかったのですが、
    解析~突破しようと思ったら
    このあたりの知識は無いと厳しそうですね。
    あと、デベロッパーツールを一通り使えるように勉強していきます。

    ログイン~ログイン後の処理に関しては
    ニコニコで通用するなら大抵のところでもいけそうだと思うので、
    今までC#はやったことがないのですが、
    これからはC#もやっていこうと思います。

    この度は本当にありがとうございました。

  22. すみません.一つお教えください.
    LogoutはLoginと同じ仕組みなんですか?

  23. 以前までvisualstudioのwebbrowserでhtmlを取得してwebbrowser上のサイトにあるボタンを押していたのですが、この方法でもボタンを押す、のような事は出来るのでしょうか?
    それとも、それもPOSTで送信した中に含まれているのでしょうか?
    よろしくお願いします。

    • ロフトくん

      >@bcさん
      こんにちは。
      この方法は、ボタンを押すことは出来ませんが、
      ボタンを押した際に発生する”ブラウザとサーバ間で行われるHTTP通信”を行うことができます(通信処理のみを行います。画面処理はありません)。

      予め、目的のサイトにあるログイン/ログアウト/掲示板に投稿/いいね!等のボタンを押した際に発生する通信の内容を調べておき、この記事のような方法でプログラムを作成して動作させると、プログラムからログイン/ログアウト/掲示板への投稿/いいね!等ができるようになります。

      (予め調べる方法としては、サイトのHTMLを見る、ブラウザのデバッグ機能(F12ボタンで起動する)で通信を見る、wireshark等のパケットキャプチャツール等で通信を見る等の方法があります。)

      また、予め調べなくてもプログラムの作り方を公開してくれているサイトもあります(いわゆる”API”です。SNSでつぶやいたり(Twitter API等)動画サイトで動画を検索(YouTube Data API)したりするのはAPIを使ってプログラムを作成しする方が作りやすいです)。

      本記事のようにプログラムで通信ができるということは人間がブラウザを操作してボタンを押さなくても良いということですので、自動化・高速化・定期処理化等が容易なのがメリットになります。

  24. Amebaへのログインを実装したいのですが
    ↓ログインページのURL↓
    https://dauth.user.ameba.jp/login/ameba

    ログインに必要なパラメータが
    accountID
    password
    csrf_token
    の3種類です。

    vals[“csrf_token”] = ??
    ??の部分にどのような記述をすればいいか解決ができずに
    レスポンスを取得できていない状況です。
    どのような記述をすればよいか教えてもらえませんか?

    C#ではじめるWebサービスプログラミングAmazonでポチりました。
    届くのが楽しみです(^^)

    • ロフトくん

      >ke-kunさん
      こんにちは。以下★の部分です。
      <input type=”hidden” name=”csrf_token” value=”★”/>

      このようなtype=”hidden”になっている項目は隠しパラメタです。
      ブラウザからログインする場合は、画面に表示されませんが、
      既に値も決められているで、Amebaのユーザはパラメタの存在を意識しません。

      しかしAmebaのサーバ側ではこの隠しパラメタに正しい値を
      指定できることをログイン条件に含めることで、
      ブラウザ以外からのログインを少し難しくしています。
      (このパラメタの値は変化しますので毎回★を抜き出す処理が必要です。)

      C#ではじめるWebサービスプログラミングはこの分野のプログラミングの原点とも言えるおすすめ書籍です^^

  25. お返事ありがとうございます。
    とても参考になりました!
    隠しパラメータの取得方法を調べてみたのですが
    HtmlAgilityPackを利用して取得する方法がありました。
    いろいろ試してみてvalueの値の抽出に成功したのですが
    リモートサーバエラー400でレスポンスを取得できませんでした。
    やはりcsrf_tokenはランダムな値であるため
    抽出の際に作成したインスタンスでのcsrf_tokenと

    POSTのために作成したインスタンス
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
    で必要とされるcsrf_tokenは違う値である
    という解釈でよろしいでしょうか?

    ↓HtmlAgilityPackでvalueを取得するソースコード↓

    WebClient web = new WebClient();
    string html = web.DownloadString(url);
    HtmlDocument doc = new HtmlDocument();
    doc.LoadHtml(html);

    var token = doc.DocumentNode.SelectNodes(“//input[@name=\”csrf_token\”]”)[0];
    Console.WriteLine(token.Attributes[“value”].Value);//取得した値の表示

  26. お返事ありがとうございます。
    とても参考になりました!
    隠しパラメータの取得方法を調べてみたのですが
    HtmlAgilityPackを利用して取得する方法がありました。
    いろいろ試してみてvalueの値の抽出に成功したのですが
    リモートサーバエラー400でレスポンスを取得できませんでした。
    やはりcsrf_tokenはランダムな値であるため
    抽出の際に作成したインスタンスでのcsrf_tokenと

    POSTのために作成したインスタンス
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
    で必要とされるcsrf_tokenは違う値である
    という解釈でよろしいでしょうか?

    ↓HtmlAgilityPackでvalueを取得するソースコード↓

    WebClient web = new WebClient();
    string html = web.DownloadString(url);
    HtmlDocument doc = new HtmlDocument();
    doc.LoadHtml(html);

    var token = doc.DocumentNode.SelectNodes(“//input[@name=\”csrf_token\”]”)[0];
    Console.WriteLine(token.Attributes[“value”].Value);//取得した値の表示

    • ロフトくん

      >ke-kun
      こんにちは。ご推測の通り、
      以下2つの通信を関連付ける何かが必要です。

      通信1(ログインページのHTMLを取得する通信)
      通信2(ログインするための通信)

      それはセッション(やクッキー)と呼ばれる情報です。

      ○通信1
      ブラウザ(やツール)はログインページが欲しいというリクエスト(HTTP GETリクエスト)をAmebaサーバに送信します。

      Amebaサーバはブラウザ(やツール)にレスポンスを返します。

      この通信の結果、ブラウザ(やツール)はAbemaサーバから2つの情報をもらいます。
      ・1つはログインページのHTMLです。csrf_tokenが書かれています。レスポンスボディと呼ばれる領域に書かれています。
      ・もう1つはセッションです。レスポンスヘッダーと呼ばれる領域に書かれており描画されません。

      ○通信2
      ブラウザ(やツール)はログインしたいというリクエスト(HTTP POSTリクエスト)を
      Amebaサーバに送信します。
      ・リクエストの地の文(ボディ)にメールアドレス、パスワード、csrf_tokenを格納します
      ・リクエストのヘッダにーに通信1でもらったセッションを格納します(ブラウザはこれをやっています。ツールはプログラミングする必要があります)

      Amebaサーバは以下をチェックしてOKならばログイン後のページをレスポンスとして返します(NGならばログインできませんというページを返します)。
      ・メールアドレス/パスワードが正しいこと
      ・通信1でブラウザに返したcsrf_tokenとセッションが一致すること

      よって、セッションに関する処理をプログラミングする必要があります。

      まずはここまで(次回へ続く)。

  27. ロフトくん

    >ke-kun
    (前回の続きです。)

    さて、セッションを扱うクラスはCookieContainerです。

    本記事の”ニコニコ動画ログインアプリのサンプル”では
    以下2つの通信で共通のCookieContainerを使用して関連付けています。

    通信1 ログインしてニコニコ動画のトッペページのHTMLを得る
    通信2 マイページを得る

    ○通信1
    ツールはニコニコのサーバにログインしたいというリクエスト(HTTP POST)を送信する
    ・リクエストの地の文にメールアドレスとパスワードを格納します(リクエストボディ)
    ・セッションを受け取れるように新規CookieContainerをリクエストヘッダに格納します。

    ニコニコのサーバはメールアドレス/パスワードが正しければ
    ログイン後のトップページをレスポンスとして返します。

    この通信の結果ツールはニコニコサーバから2つの情報をもらいます。
    ・1つはログイン後のトップページです(レスポンスボディ)
    ・もう1つはセッション情報で(レスポンスヘッダ)、実装的にはリクエストヘッダに格納しておいたCookieContainerに格納されます(ここがポイントです)。

    ○通信2
    ツールはマイページが欲しいというリクエスト(HTTP GET)を送信する
    ・この時、リクエストヘッダに通信1でもらったセッション(CookieContainer)を格納しています。

    ニコニコのサーバは受け取ったセッションを見て誰のマイページを返せばいいか判断しレスポンスを返します。

    この例では以下通信間で共通のCookieContainerを使用して通信を関連付けました。
    通信1 HTTP POST(ログイン処理)

    通信2 HTTP GET(マイページ取得)

    Abemaにログインする際は以下通信間で共通のCookieContainerを使用して通信を関連付けるとよいです。
    通信1 HTTP GET(ログインページHTML取得)

    通信2 HTTP PSOT(ログイン処理)

    さらに
    通信1 HTTP GET(ログインページHTML取得)

    通信2 HTTP PSOT(ログイン処理)

    通信3 HTTP GET(ログイン後の情報が得られる何らかのページA)

    通信4 HTTP GET(ログイン後の情報が得られる何らかのページB)

    通信n (略)

    のように、複数の通信で同じセッションを使うことで、
    同一ユーザとして通信ができます。

    • ロフトくん

      >ke-kun
      長くなりましたが、通信1,2それぞれに
      同じCookieContainerオブジェクトを
      使用するのがこつです。

      前準備

      // セッション・クッキー格納コンテナ
      CookieContainer cc = new CookieContainer();
      
      // UserAgent
      String userAgent = "YOUR_APPLICATION_NAME"// 普通はIEやChromeやFF等のブラウザ名;
      

       
       
      通信1 HTTP GET(ログインページHTML取得)

      HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://dauth.user.ameba.jp/login/ameba");
      req.Method = "GET";
      req.CookieContainer = cc;// 空のセッション(クッキー)を使用する(Amebaのサーバからセッションをもらって格納する)
      
      // レスポンス取得(大幅に略)
      String loginPageHTML = (略);
      

       
       
      通信2 HTTP PSOT(ログイン処理)

      // ログインパラメタ生成
      var mail = "YOUR@EMAIL.ADDRESS";//TODO 変更
      var pass = "YOUR_PASSWORD";// TODO 変更
      var csrf_token = getToken(loginPageHTML);//TODO csrf_tokenを抜き出す処理
      
      byte[] param = Encoding.UTF8.GetBytes("accountId=" + mail + "&password=" + pass + "&csrf_token=" + csrf_token);
      
      // リクエスト生成
      HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://dauth.user.ameba.jp/accounts/login");
      req.Method = "POST";
      req.UserAgent = userAgent;
      req.ContentType = "application/x-www-form-urlencoded";
      req.ContentLength = param.Length;
      req.CookieContainer = cc;// 引き続きセッション(クッキー)を使用する(通信1でAmebaのサーバからもらったセッションを使う)ことで通信1と関連付ける
      
      // リクエスト送信・レスポンス取得(大幅に略)
      String myPageHTML = (略);// マイページのHTML(自分のユーザ名等ログインしないと得られない情報が記載されているはず)
      
      • 無事にAmebaにログインすることができました!
        説明がとてもわかりやすく、HTTPリクエストやCookieについて
        無知な自分でも理解することができました。
        本当にありがとうございました!

  28. ピンバック:[VB.NET] -参考リンク- FTP

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です