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

̃Gg[͂ĂȃubN}[Nɒlj

クライアントアプリからの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();

・GETリクエストによるクッキー取得

GETリクエストにより、クッキー及び認証後サイトのHTMLソースが取得できます。

            //HTTP GETによるクッキーの取得
            //GET実行
            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();

			//HTTP GETによるクッキーの取得
            //GET実行
            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


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

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

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

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

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

  5. >名無しさん
    こんにちは。
    若干古い書籍ですが『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

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

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

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

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

    この記事を参考にして
    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は可変するようですが
    どう対処すれば良いのでしょうか?

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

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

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

    ありがとうございます。
    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

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

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

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

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

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

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

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

  13. >はてなっちさん
    こんにちは。
    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など各ブラウザに付属のデバッガツールを活用されるのが良いと思います。

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

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

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

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

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

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

コメントを残す

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

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>