作成日: 2004/02/28

ASP.NET でクッキーレス

概要

ASP.NET を使うと Web.config に設定するだけで、Web アプリケーションをクッキーレスなものに変更することができます。 ですが、ASP.NET の認証機構を使っており、かつ ASP 以外の Web システムからユーザ ID、パスワードなどを POST させて認証を行ってから、 メインページなどへ遷移させたい場合、そのままでは、うまくいかないことがあります。 これは ASP.NET がブラウザからセッション ID を含まない URL を要求されると、レスポンスコード 302 を返して、 ブラウザにセッション ID を含んだ URL へリダイレクトさせようとするためです。 何とかこれを回避したくて、あれこれと試し、姑息な手を考えてみました。 なお、以下の説明では Windows XP Professional 上で、.NET C# 2002 & IIS 5.1(Web アプリケーション用) を使用しています。

ASP.NET で作るログインページ

ASP.NET には認証機構が組み込まれているため、以前の ASP などでは、自前で行っていた認証済みかどうかの判断などは すべて ASP.NET が行ってくれます。
最初に認証機構を組み込んだページを作成してみます。ここでは、ログインページを表示し、ユーザ ID、パスワードを入力して ログインするだけの簡単なものを作成します。では、早速‥。
IIS が起動しているのを確認してから .NET を起動します。メニューから [ファイル] - [新規作成] - [プロジェクト] を選び、 表示される [新しいプロジェクト] ダイアログで、プロジェクトの種類に [Visual C# プロジェクト]、テンプレートで [ASP.NET Web アプリケーション] を選択します。[場所] には [http://localhost/LoginTest] と入力し、[OK] をクリックします。

新しいプロジェクト

[新しい Web の作成] ダイアログが表示されますので、しばらく待っていると生成されたプロジェクトとページが表示されます。

新しいWebの作成 デザイン画面

では、ログインページを作成します。[ソリューション エクスプローラ] から [WebForm1.aspx] をクリックしプロパティを表示します。 [ファイル名] に表示されている [WebForm1.aspx] を [Login.aspx] に変更します。

名称を変更する

ログイン時にユーザIDとパスワードを入力するためのテキストボックスを 2 つと、ログインのためのボタンを配置します。 [ツールボックス] - [Web フォーム] から [TextBox] を選択し、画面上に配置します。上段に配置したテキストボックスの ID を [UserID]、 下段に配置したテキストボックスの ID は [PassWord] に変更してください。 同じく [ツールボックス] - [Web フォーム] から [Button] を選択して、画面上に配置します。ボタンの ID は [GoLogin] に変更します。
後は、適当にラベルを張ったりしてログイン画面らしく仕上げてください。
※静的なコントロールを配置する場合、[Web フォーム] のコントロールを使わず [HTML] のコントロールを使用した方が、 パフォーマンスが良いという話をきいたことがあります。以下でも、ログイン画面の説明やユーザID、パスワードの説明などの、 動的に変わることのないラベルは、[ツールボックス] - [HTML] から [Label] を選択して配置しました。

コントロールを配置する

また、タイトルもログインページらしく変更してみました。

タイトルを変更する

配置が済んだら、思い通りの画面になっているかを確認するために、とりあえず動かしてみます。メニューから [デバッグ] - [開始] を選択します。IE が起動して作成した画面が表示されると思います。

ログインページを表示してみる

もし、以下のようなダイアログが表示された場合、プロジェクトにスタートページが設定されていません。

スタートページが設定されていない場合

スタートページの設定は、[ソリューション エクスプローラ] から [Login.aspx] を右クリックし、 表示されるポップアップメニューから [スタート ページに設定] をクリックして行います。

スタートページを設定する

あるいは、以下のようなダイアログが表示された場合、実行しているユーザが IIS を実行しているマシンの Administrators グループに属していないため、デバッグモードで実行することができないことをあらわしています。
とりあえず、[いいえ] をクリックしてダイアログを閉じてください。

デバッグを開始できない場合

この場合、ユーザを Administrators グループに属させることでデバッグモードで実行できるようになります。
が、ユーザを Administrators グループに属させずにデバッグモードで実行させたい場合は、以下の手順を踏んで、 ASP.NET をログインユーザの権限で実行させるようにしてください。

ASP.NET の実行時の権限を変更するには、C:\WINDOWS\Microsoft.NET\Framework\vX.X.X\CONFIG 以下の [machine.config] ファイルに変更を加える必要があります。
パス中の vX.X.X の部分は ASP.NET から参照されている .NET のバージョンに依存します。.NET 2002 を使用しており、かつ、 上位バージョンの .NET Framework をマシンにインストールしていない場合は、IIS から使用される ASP.NET のバージョンは 1 になっているはずです。
マシンに複数の .NET Framework をインストールしている場合は、ASP.NET から参照されている .NET のバージョンに注意してください。
私の環境にはバージョン 1 と バージョン 1.1 の .NET Framework をインストールしていたため、ASP.NET は バージョン 1.1 の Framework を参照していました。そのため、[machine.config] は [C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\CONFIG\machine.config] になりますので、これを変更しました。

適当なエディタを使って [machine.config] ファイルを開きます。 <processModel> タグの [userName] にデバッグモード実行時のログインユーザの ID を、 [password] にログインユーザのパスワードを設定してください。

設定ファイルを変更する

設定を保存した後、IIS のサービスを再起動すれば、ASP.NET はログインユーザの権限で実行されるようになります。

再起動後の ASP.NET のプロセス

次にログイン後に表示されるページを追加します。ここでは、これをログイン後に表示されるメニュー画面だと仮定しています。
[ソリューション エクスプローラ] からプロジェクトを右クリックし、表示されるポップアップメニューから [追加] - [新しい項目の追加] を選択します。

新しいページを追加する

表示される [新しい項目の追加] ダイアログで [Web フォーム] を選択し、[ファイル名] に [Menu.aspx] と入力し、 [開く] をクリックします。

ファイル名を設定する

メニューページは表示されるだけなので、適当なラベルを載せてレイアウトしてください。

メニューページをレイアウトする

次に、ASP.NET のフォーム認証機能を有効にします。 [Web.config] を開き、<authentication> セクションおよび <authorization> セクションを以下のように変更してください。 もし、セクションが存在しない場合は追加してください。

認証機能を有効にする

次に認証のためのプログラムコードを追加します。[Login.aspx] を開き、[ログイン] ボタンをダブルクリックして、 ハンドラコードを以下のように追加します。ここでは、ユーザIDが "Foo"、パスワードが "Bar" の時のみ認証するようにしています。

認証コードを追加する

追加が済んだら、保存して実行します。メニューから [デバッグ] - [開始] を選択します。IE が起動してログイン画面が表示されます。
正しいユーザ ID やパスワードを入力してログインできることや、間違ったユーザ ID、パスワードではログインできないこと、また、 ログイン前にいきなり [Menu.aspx] を要求してもログイン画面へリダイレクトされることを確認してください。
※ただし、一旦ログインした後は、メニュー画面やその他のページを直接要求しても表示されるようになります。

正常にログインした場合

正常にログインした場合

いきなり [Menu.aspx] を要求した場合

いきなり [Menu.aspx] を要求した場合
クッキーレスにする

次に作成した Web アプリケーションをクッキーレスにします。プログラミングは不要です。[Web.config] を開き、 <sessionState> の [cookieless] を "true" にするだけです。

クッキーレスにする設定

設定を保存したら、起動してみます。

ログインページを表示してみる

URL が [http://localhost/LoginTest/(lazdqb3mngor115525340wfc)/Login.aspx] となっており、 クッキーなしでセッション情報をサーバに渡すために URL にセッション ID が埋め込まれた形になっているのがわかります。

他システムからの POST

さて、ここで、最近はやりのワンストップサービスを無理やり実現しなければいけなくなったと仮定します。 さらに、他システムからは POST でユーザ ID、パスワードを受け取り、ログイン処理を行った後、 メニュー画面に遷移することになったとします。かなり強引ですが・・ (^^;)。
とりあえず、他システム側のページを作ります。ユーザ ID、パスワードを入力しログインするだけのページです。

他システムからのログインページ

ソースはこんな感じです。ファイル名は適宜好きなように保存してください。ここでは、[other.html] として保存しました。

<html>
<head>
<title>他システムのページ</title>
</head>
<body>
    <form name="main" action="http://localhost/LoginTest/Login.aspx" method="post">
        <table>
            <tr>
                <td>ユーザID:</td><td><input type="text" name="userID"></td>
            </tr>
            <tr>
                <td>パスワード:</td><td><input type="text" name="passWord"></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="ASP.NET で作成したメニューページへ"></td>
            </tr>
        </table>
    </form>
</body>
</html>

次に ASP.NET 側のログインページを POST されたユーザ ID、パスワードでログイン処理を行うように修正します。 [Login.aspx] の [Page_Load] を以下のように変更してください。

ログインするためのコード

これで、完了です。では、さっそく動かしてみます。
メニューから [デバッグ] - [開始] を選択します。IE が起動してログイン画面が表示されます。
ここで、別に IE を起動して、先ほど作った [ohter.html] を開きます。ユーザ ID に "Foo"、パスワードに "Bar" と入力し、 [ASP.NET で作成したメニューページへ] をクリックしてみてください。
どうでしょうか・・。あれ・・?。ログインできませんねぇ。ログインページへリダイレクトされてしまいます。

他システムからログインしようとするが・・

他システムからのログイン

ログインページへリダイレクトされてしまう

ログインページへリダイレクトされた

うーん。なんででしょう・・。クッキーレスにしたことと関係がありそうなので、とりあえず、クッキーレスをやめてみましょう。 [Web.config] を開き、<sessionState> の [cookieless] を "false" にしてください。

クッキーを有効にする

設定を保存したら、もう一度、先ほどと同じことをしてみてください。 どうでしょうか。今度はうまくいったようです。

他システムからログイン

他システムからのログイン

無事メニューページが表示された

メニューページが表示された
ブラウザ - サーバ間のやり取り

なぜ、クッキーレスにしたときにはログインできなかったのでしょう。 まず、無事ログインできたとき(クッキーあり)のブラウザ - サーバ間でやり取りされた内容をみてみます。
※ブラウザ - サーバ間に通信をリレーする簡易なプログラムをいれてログを取りました。単一マシンで実行したので、 ブラウザ -> リレープログラムのポート 8080 -> IIS のポート 80 という形にしました。 そのため、ブラウザからの送信先ホストが "Host: localhost:8080" となっていますが、気にしないでください (^^;)。

最初のブラウザからサーバに対して POST を行ったときの内容です。ボディ部で "userID=Foo&passWord=Bar" としてユーザ ID、パスワードの値が POST されているのがわかります。

POST /LoginTest/Login.aspx HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, */*
Accept-Language: ja
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)
Host: localhost:8080
Content-Length: 23
Connection: Keep-Alive
Cache-Control: no-cache

userID=Foo&passWord=Bar

サーバからのレスポンスの内容です。レスポンスコード 302 を返し、新しい URI を Location で示しています。 新しい URI は "/LoginTest/Menu.aspx" ですので、メニューページになっています。
また、"Set-Cookie: ASP.NET_SessionId=uc11e1idhwxsi355mom0m345; path=/" としてセッション ID がクッキー情報として送られてきているのが分かります。

HTTP/1.1 100 Continue
Server: Microsoft-IIS/5.1
Date: Wed, 18 Feb 2004 03:23:12 GMT
X-Powered-By: ASP.NET

HTTP/1.1 302 Found
Server: Microsoft-IIS/5.1
Date: Wed, 18 Feb 2004 03:23:12 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Location: /LoginTest/Menu.aspx
Set-Cookie: ASP.NET_SessionId=uc11e1idhwxsi355mom0m345; path=/
Set-Cookie: .ASPXAUTH=1B560AD74D099317874F44C931EFB408E0126C4D1482078881AA353603269DFC37BB958FDB35925B95F42000F6D7E1E5679EEC6C88D828B0A1D2386572483C10; path=/
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 137

<html><head><title>Object moved</title></head><body>
<h2>Object moved to <a href='/LoginTest/Menu.aspx'>here</a>.</h2>
</body></html>

クライアントは指定された URI に GET を行っています。要求先 URI はメニューページで、 クッキー情報もあわせて送信しているのがわかります。

GET /LoginTest/Menu.aspx HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, */*
Accept-Language: ja
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)
Host: localhost:8080
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: ASP.NET_SessionId=uc11e1idhwxsi355mom0m345; .ASPXAUTH=1B560AD74D099317874F44C931EFB408E0126C4D1482078881AA353603269DFC37BB958FDB35925B95F42000F6D7E1E5679EEC6C88D828B0A1D2386572483C10

最終的なページがサーバから送られてきました。これはメニュー画面の内容です。

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
Date: Wed, 18 Feb 2004 03:23:12 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 844


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
	<HEAD>
		<title>Menu</title>
		<meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">
		<meta name="CODE_LANGUAGE" Content="C#">
		<meta name="vs_defaultClientScript" content="JavaScript">
		<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
	</HEAD>
	<body MS_POSITIONING="GridLayout">
		<form name="Menu" method="post" action="Menu.aspx" id="Menu">
<input type="hidden" name="__VIEWSTATE" value="dDwtMTI3OTMzNDM4NDs7PvTzEtYE/IDrnZ7v7qQL2Ywo3pC1" />

			<FONT face="MS UI Gothic">
				<DIV style="DISPLAY: inline; Z-INDEX: 101; LEFT: 16px; WIDTH: 296px; POSITION: absolute; TOP: 16px; HEIGHT: 40px" ms_positioning="FlowLayout">ログインに成功しました。</DIV>
			</FONT>
		</form>
	</body>
</HTML>

次に、ログインできなかったとき(クッキーなし)のブラウザ - サーバ間でやり取りされた内容をみてみます。
同じくリレープログラムが入っているため、ブラウザからの送信先ホストが "Host: localhost:8080" となっていますが、 気にしないでください

ブラウザからサーバに対して行った POST の内容です。クッキーありのときと違いはありません。

POST /LoginTest/Login.aspx HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, */*
Accept-Language: ja
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)
Host: localhost:8080
Content-Length: 23
Connection: Keep-Alive
Cache-Control: no-cache

userID=Foo&passWord=Bar

サーバからのレスポンスの内容です。レスポンスコード 302 を返し、新しい URI を Location で示しています。
クッキー情報が無いのがわかります。また、新しい URI はセッション ID を含んだ "/LoginTest/(zpeuvzfbhszx5d55haasy5yv)/Login.aspx" ですので、ログインページになっています。

HTTP/1.1 100 Continue
Server: Microsoft-IIS/5.1
Date: Wed, 18 Feb 2004 04:14:04 GMT
X-Powered-By: ASP.NET

HTTP/1.1 302 Found
Server: Microsoft-IIS/5.1
Date: Wed, 18 Feb 2004 04:14:04 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Location: /LoginTest/(zpeuvzfbhszx5d55haasy5yv)/Login.aspx
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 165

<html><head><title>Object moved</title></head><body>
<h2>Object moved to <a href='/LoginTest/(zpeuvzfbhszx5d55haasy5yv)/Login.aspx'>here</a>.</h2>
</body></html>

クライアントが指定された URI に対して行った GET の内容です。要求先 URI がログインページになっており、また、 クッキー情報はありません。

GET /LoginTest/(zpeuvzfbhszx5d55haasy5yv)/Login.aspx HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, */*
Accept-Language: ja
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)
Host: localhost:8080
Connection: Keep-Alive
Cache-Control: no-cache

最終的なページがサーバから送られてきました。これはログイン画面の内容です。

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
Date: Wed, 18 Feb 2004 04:14:04 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 1712


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
	<HEAD>
		<title>ログインページ</title>
		<meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">
		<meta name="CODE_LANGUAGE" Content="C#">
		<meta name="vs_defaultClientScript" content="JavaScript">
		<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
	</HEAD>
	<body MS_POSITIONING="GridLayout">
		<form name="Form1" method="post" action="Login.aspx" id="Form1">
<input type="hidden" name="__VIEWSTATE" value="dDwtMzg4MDA0NzA7Oz4MLJGOBKpRUTrd0zdKbwbku7m7bA==" />

			<FONT face="MS UI Gothic">
				<input name="UserID" type="text" id="UserID" style="width:128px;Z-INDEX: 101; LEFT: 96px; POSITION: absolute; TOP: 64px" />
				<input name="PassWord" type="text" id="PassWord" style="width:128px;Z-INDEX: 102; LEFT: 96px; POSITION: absolute; TOP: 96px" />
				<input type="submit" name="GoLogin" value="ログイン" id="GoLogin" style="width:96px;Z-INDEX: 103; LEFT: 96px; POSITION: absolute; TOP: 128px" />
				<DIV style="DISPLAY: inline; Z-INDEX: 104; LEFT: 16px; WIDTH: 304px; POSITION: absolute; TOP: 16px; HEIGHT: 40px" ms_positioning="FlowLayout">ログイン画面です。ユーザID、パスワードを入力した後、ログインボタンをクリックしてください。</DIV>
				<DIV style="DISPLAY: inline; Z-INDEX: 105; LEFT: 16px; WIDTH: 72px; POSITION: absolute; TOP: 64px; HEIGHT: 24px" ms_positioning="FlowLayout">ユーザID:</DIV>
				<DIV style="DISPLAY: inline; Z-INDEX: 106; LEFT: 16px; WIDTH: 72px; POSITION: absolute; TOP: 96px; HEIGHT: 24px" ms_positioning="FlowLayout">パスワード:</DIV>
			</FONT>
		</form>
	</body>
</HTML>

整理してみると、以下のようになるでしょうか。

ログイン成功時(クッキーあり)

クッキーあり

ログイン失敗時(クッキーなし)

クッキーなし

どうやら、ログインページ(Login.aspx) の Page_Load に記述したログインの処理がクッキーレス時にはうまく働かないようです。

デバッグしてみる

困ったときは、デバッガを頼ってみましょう。まず、またまたクッキーレスに設定します。 [Web.config] を開き、<sessionState> の [cookieless] を "true" にしてから保存してください。
次に、ログイン処理にブレークポイントを設定し、どのように動作しているのかみてみます。
[Login.aspx] の [Page_Load] ハンドラを開き、

sUserID = Request.Params["userID"];

の箇所にブレークポイントを設定します。当該行の左端の枠のところをクリックすると、 その行にブレークポイントが設定できます。
※下図のえび茶色の●が表示されている所です。

ブレークポイントを設定する

では、起動します。メニューから [デバッグ] - [開始] を選択します。IE が起動すると、 すぐにブレークポイントで処理が停止します。

ブレークポイントで停止した

これは、スタートページを表示するときにここを通るためです。そのまま、 メニューから [デバッグ] - [続行] を選択し、処理を進めてください。IE にログイン画面が表示されます。

次に別に IE を起動し、[ohter.html] を開きます。ユーザ ID、パスワードにそれぞれ、"Foo"、"Bar" と入力してから、[ASP.NET で作成したメニューページへ] をクリックします。

他システムからのログイン

再び、ブレークポイントで処理が停止すると思います。
この状態から、ステップ実行していきます。メニュー - [デバッグ] - [ステップ オーバー] を選択するか、 または [F10] を押してください。1 ステップづつコードが実行されます。
デバッグ中は変数の上にマウスカーソルをかざせば、その変数の値がポップアップで表示されます。下図では、 ウォッチ式に追加して表示しています。
変数 sUserID、sPassWord の値はどうなっているでしょうか。おや?、null になっているようです。
これでは、ログイン処理をしたくともできないわけです。

ステップ実行する

原因がわかりましたので、デバッグを停止します。メニュー - [デバッグ] - [デバッグの停止] を選択すれば、 デバッグ実行を停止することができます。

クッキーレス時の動作

実は、先ほど ブラウザ - サーバ間のやり取り での図 ログイン失敗時(クッキーなし) は少し間違っています。実際には、以下のような感じでしょうか。

クッキーレス時の動作

ブラウザから POST されたとき、要求先 URI はセッション ID を含まない形式 [http://localhost/LoginTest/Login.aspx] になっています。が、クッキーレスの場合、ASP.NET は URI にセッション ID を含めた形で要求してもらう必要があるので、 セッション ID を含んだ [http://localhost/LoginTest/(zpeuvzfbhszx5d55haasy5yv)/Login.aspx] を指示してブラウザに リダイレクトさせようとします。
ブラウザはこの要求を受けてリダイレクトするのですが、この際、POST ではなく GET してしまうため、送信すべきユーザ ID、 パスワードが送られず、ログイン処理の際にそれぞれの値が null になってしまっているのです。

対応策その 1

対応策の 1 つは、初回の POST を GET にしてしまうことです。GET にした場合、ユーザ ID、 パスワードは URI の後ろにくっついた形で要求され、ASP.NET からリダイレクト先として指示される URI にも引き継がれます。
ASP.NET では、ログイン処理でブラウザからのリクエストパラメータを取得するための

sUserID = Request.Params["userID"];
sPassWord = Request.Params["passWord"];

という構文 1 つで GET にも POST にも区別無くパラメータを取得できるようになっていますので、 プログラムコードを変更する必要はありません。

以下に、初回要求を GET に変更した場合のブラウザ - サーバ間のやり取りを示します。
使用した HTML ソースは以下のようになります。
※POST を GET に変えただけですが・・。

<html>
<head>
<title>他システムのページ</title>
</head>
<body>
    <form name="main" action="http://localhost/LoginTest/Login.aspx" method="get">
        <table>
            <tr>
                <td>ユーザID:</td><td><input type="text" name="userID"></td>
            </tr>
            <tr>
                <td>パスワード:</td><td><input type="text" name="passWord"></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="ASP.NET で作成したメニューページへ"></td>
            </tr>
        </table>
    </form>
</body>
</html>

また、他の例と同じようにブラウザ - サーバ間には、リレープログラムが入っているため、 ブラウザからの送信先ホストが "Host: localhost:8080" となっていますが、 気にしないでください。

ブラウザからの GET 要求です。要求先 URI の後ろにユーザID、パスワードがくっついているのがわかります。

GET /LoginTest/Login.aspx?userID=Foo&passWord=Bar HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, */*
Accept-Language: ja
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)
Host: localhost:8080
Connection: Keep-Alive

サーバからの応答です。ブラウザに対し、セッションID を含んだ URI にリダイレクトさせようとしています。
リダイレクト先として示される値 "Location: /LoginTest/(gyywne451yzdh255axmkel55)/Login.aspx?userID=Foo&passWord=Bar" には、 ユーザID、パスワードが含まれているのが分かります。

HTTP/1.1 302 Found
Server: Microsoft-IIS/5.1
Date: Wed, 18 Feb 2004 11:55:36 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Location: /LoginTest/(gyywne451yzdh255axmkel55)/Login.aspx?userID=Foo&passWord=Bar
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 193

<html><head><title>Object moved</title></head><body>
<h2>Object moved to <a href='/LoginTest/(gyywne451yzdh255axmkel55)/Login.aspx?userID=Foo&passWord=Bar'>here</a>.</h2>
</body></html>
サーバの指示に従って、ブラウザが "/LoginTest/(gyywne451yzdh255axmkel55)/Login.aspx?userID=Foo&passWord=Bar" を要求しなおしています。 このときも、ユーザID、パスワードが URI にきちんと含まれているのがわかります。
GET /LoginTest/(gyywne451yzdh255axmkel55)/Login.aspx?userID=Foo&passWord=Bar HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, */*
Accept-Language: ja
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)
Host: localhost:8080
Connection: Keep-Alive

サーバがさらに、新しい URI を指示してきました。新しい URI は "/LoginTest/(gyywne451yzdh255axmkel55)/Menu.aspx" となっていますので、 メニューページです。もう URI の後ろにユーザ ID、パスワードはくっついていません。
この時点で、サーバ側のログイン処理が完了し、メニューページへ遷移させようとしているのがわかります。
また、クッキーレスなのになぜか、クッキー情報が入っています。 真偽のほどは分かりませんが、クッキーレスにしても同一マシン内でやり取りする場合には、 クッキー情報が付加されるという話をきいたことがありますので、そのためかもしれません。 ただし、セッション ID はクッキー情報には含まれておらず、URI で指示されています。

HTTP/1.1 302 Found
Server: Microsoft-IIS/5.1
Date: Wed, 18 Feb 2004 11:55:36 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Location: /LoginTest/(gyywne451yzdh255axmkel55)/Menu.aspx
Set-Cookie: .ASPXAUTH=7BFCCD0C880B5ADBC7807E06A3770E545DF05A07DFA8E9DEB93ADBF2D135B972462D8C5EC8CC91FCE015931BA4DC4FB72FAD00D2D2AB4FCFB6DAD8C801238A71; path=/
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 164

<html><head><title>Object moved</title></head><body>
<h2>Object moved to <a href='/LoginTest/(gyywne451yzdh255axmkel55)/Menu.aspx'>here</a>.</h2>
</body></html>

ブラウザがメニューページを要求しています。
なお、ここでもクッキー情報が含まれています。ブラウザのクッキー処理を「ブロックする」にして行ってみたのですが、 クッキーの送信を止めることができませんでした。同一マシン内なため、送られているのかもしれません。 が、セッション ID に関する値はやはり含まれておらず、URI で示されるだけとなっています。

GET /LoginTest/(gyywne451yzdh255axmkel55)/Menu.aspx HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, */*
Accept-Language: ja
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)
Host: localhost:8080
Connection: Keep-Alive
Cookie: .ASPXAUTH=7BFCCD0C880B5ADBC7807E06A3770E545DF05A07DFA8E9DEB93ADBF2D135B972462D8C5EC8CC91FCE015931BA4DC4FB72FAD00D2D2AB4FCFB6DAD8C801238A71

メニューページが送られてきました。

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
Date: Wed, 18 Feb 2004 11:55:36 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 844


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
	<HEAD>
		<title>Menu</title>
		<meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">
		<meta name="CODE_LANGUAGE" Content="C#">
		<meta name="vs_defaultClientScript" content="JavaScript">
		<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
	</HEAD>
	<body MS_POSITIONING="GridLayout">
		<form name="Menu" method="post" action="Menu.aspx" id="Menu">
<input type="hidden" name="__VIEWSTATE" value="dDwtMTI3OTMzNDM4NDs7PvTzEtYE/IDrnZ7v7qQL2Ywo3pC1" />

			<FONT face="MS UI Gothic">
				<DIV style="DISPLAY: inline; Z-INDEX: 101; LEFT: 16px; WIDTH: 296px; POSITION: absolute; TOP: 16px; HEIGHT: 40px" ms_positioning="FlowLayout">ログインに成功しました。</DIV>
			</FONT>
		</form>
	</body>
</HTML>

やり取りを簡単にまとめると以下のようになるでしょうか。

クッキーレス時の動作
対応策その 2

要求を GET に変える方法でもうまくいくのですが、ユーザ ID、パスワードが URI に埋め込まれてしまうため、 アドレスバーを表示している場合には、ユーザに丸見えになってしまいます。できれば、POST にして隠しておきたいところです。
では、いきなりセッション ID を含んだ URI に POST 要求してみたらどうでしょうか?。例えば、最初の方に使われていた、 セッション ID [lazdqb3mngor115525340wfc] を使って POST してみたらどうなるでしょう。
今、セッションのタイムアウト時間は 20 分にしてあります。ここへ書き進めるまでに既に 20 分以上たっていますので、 仮に IIS 内に セッション ID [lazdqb3mngor115525340wfc] でセッションが確保されていたとしても、もう解放されているはずです。

以下のような HTML を作成し、[other2.html] として保存し、これを使ってログインしてみました。

<html>
<head>
<title>他システムのページ(無理やりPOST)</title>
</head>
<body>
    <form name="main" action="http://localhost/LoginTest/(lazdqb3mngor115525340wfc)/Login.aspx" method="post">
        <table>
            <tr>
                <td>ユーザID:</td><td><input type="text" name="userID"></td>
            </tr>
            <tr>
                <td>パスワード:</td><td><input type="text" name="passWord"></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="ASP.NET で作成したメニューページへ"></td>
            </tr>
        </table>
    </form>
</body>
</html>

なんと、ログインできるではないですか。以下はその際のブラウザ - サーバ間のやり取りの内容です。

ブラウザからの要求です。要求先 URI には、いきなりセッション ID が埋め込まれています。

POST /LoginTest/(lazdqb3mngor115525340wfc)/Login.aspx HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, */*
Accept-Language: ja
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)
Host: localhost:8080
Content-Length: 23
Connection: Keep-Alive
Cache-Control: no-cache

サーバからの応答です。新しい URI として "Location: /LoginTest/(lazdqb3mngor115525340wfc)/Menu.aspx" と指示されています。 この時点でログイン処理が完了し、メニューページに遷移するように指示がきているのがわかります。

HTTP/1.1 100 Continue
Server: Microsoft-IIS/5.1
Date: Wed, 18 Feb 2004 12:32:02 GMT
X-Powered-By: ASP.NET

HTTP/1.1 302 Found
Server: Microsoft-IIS/5.1
Date: Wed, 18 Feb 2004 12:32:02 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Location: /LoginTest/(lazdqb3mngor115525340wfc)/Menu.aspx
Set-Cookie: .ASPXAUTH=E76996DB09A1A715B30B99AC79F2C51CC78D885BDB8531216630207B544351AC4382CB881795519B3B876061BB86EA401733352B0E3184ADF80E58DDD4D4C461; path=/
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 164

<html><head><title>Object moved</title></head><body>
<h2>Object moved to <a href='/LoginTest/(lazdqb3mngor115525340wfc)/Menu.aspx'>here</a>.</h2>
</body></html>

ブラウザからのメニューページの要求です。

userID=Foo&passWord=BarGET /LoginTest/(lazdqb3mngor115525340wfc)/Menu.aspx HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, */*
Accept-Language: ja
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)
Host: localhost:8080
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: .ASPXAUTH=E76996DB09A1A715B30B99AC79F2C51CC78D885BDB8531216630207B544351AC4382CB881795519B3B876061BB86EA401733352B0E3184ADF80E58DDD4D4C461

メニューページが送られてきました。

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
Date: Wed, 18 Feb 2004 12:32:02 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 844


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
	<HEAD>
		<title>Menu</title>
		<meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">
		<meta name="CODE_LANGUAGE" Content="C#">
		<meta name="vs_defaultClientScript" content="JavaScript">
		<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
	</HEAD>
	<body MS_POSITIONING="GridLayout">
		<form name="Menu" method="post" action="Menu.aspx" id="Menu">
<input type="hidden" name="__VIEWSTATE" value="dDwtMTI3OTMzNDM4NDs7PvTzEtYE/IDrnZ7v7qQL2Ywo3pC1" />

			<FONT face="MS UI Gothic">
				<DIV style="DISPLAY: inline; Z-INDEX: 101; LEFT: 16px; WIDTH: 296px; POSITION: absolute; TOP: 16px; HEIGHT: 40px" ms_positioning="FlowLayout">ログインに成功しました。</DIV>
			</FONT>
		</form>
	</body>
</HTML>

あまりにあっけないので、拍子抜けしてしまいましたが、どうやら初回の POST 時にセッション ID を埋め込んでおけば、 ログイン処理が動作するようです。では、どんな値をセッション ID として埋め込めば APS.NET は要求を受理してくれるのでしょうか。

結論からいえば、セッション ID は以下の要件を満たしておけば、受け入れられるようです。

  • 24 桁であること
  • a-z のアルファベット、0-5 の数字で構成されていること

これ以外の組み合わせも試してみましたが、受け入れられない場合があったため、要件から除外しました。
上記を利用して、毎回新たなセッション ID を埋め込んだ URL に POST するようにサンプルを作ってみましたので、 試してみてください。なお、当該 HTML は javascript を使用し、また、セッション ID の一部にホスト名を使用するために、 ActiveX オブジェクトを使用しているため、javascript、Active X ともに利用できるように、 ブラウザのオプションを調整してから実行してください。

なお、上記のセッション ID の仕様については、ランダムな組み合わせで 10 万回程度の試行を行い、すべてが受理されたことは確認していますが、 裏づけとなる資料があるわけではありません。色々と調べてみたのですが、そのような資料を見つけることができませんでした。 ので、今後の ASP.NET のバージョンでも有効な要件であるかは保証できません。あくまで参考程度に考えていただけると良いと思います。
また、もし業務などで使う際には、時間的・空間的に常に一意になるようにセッション ID を作らないと、 同時に複数のユーザ間で同じセッション ID を使ってしまった場合、他人のセッションを乗っ取ってしまうことになりますので、 その辺りは要求仕様と天秤にかけて作り込んでみてください。

サンプルソース
other.html
ここで使ったサンプル HTML です。
otherget.html
ここで使ったサンプル HTML です。
other2.html
ここで使ったサンプル HTML です。
other3.html
最後のサンプル HTML です。 javascript、Active X ともに使える状態で試してください。
LoginTest.zip (11.0 KB)
作成した Web アプリケーションです。