トップ回答者
同一セッションの2画面目が新規セッションとして扱われる事象

質問
-
掲題の事象について、手詰まっておりますため、
ご助力を頂戴したく、お願い致します。ASP.NET Frameworkの不具合でしょうか。
--------------------------------------------------
現象
--------------------------------------------------
同一プロセスのIEから2連続で開かれたASP.NET画面が
同じセッション(ID)であるにも関わらず、
2画面目のSession_Start内の「IsNewSession」で
「true」となる。--------------------------------------------------
環境
--------------------------------------------------
開発環境:Visual Studio 2010、.NET Framework4.0
動作環境:
【サーバPC】
Windows Server 2008 Standard with SP2 32bit
.NET Framework4.0
IIS7.0
【クライアントPC】
Windows 7 Professional with SP1 32bit
IE8--------------------------------------------------
手順
--------------------------------------------------
open.htmlからpost.htmlを意図的に2連続して
window.open()しています。
post.htmlではASP.NETに渡したいデータをポストしています。--------------------------------------------------
open.html
--------------------------------------------------// 1画面目
window.open("post.html", '', 'width=100,height=100');
// 2画面目
window.open("post.html", '', 'width=100,height=100');--------------------------------------------------
post.html
--------------------------------------------------<BODY onload="document.f.submit();">
<FORM METHOD="post" NAME="f" ACTION="../ASP_APP/PostData.aspx">
<INPUT TYPE="hidden" NAME="post_data" VALUE="でーた">
</FORM>
</BODY>--------------------------------------------------
ASP_APP Global.aspx.cs
--------------------------------------------------void Session_Start(object sender, EventArgs e)
{
if (!Session.IsNewSession)
return;// 以降、固有処理
}
回答
-
> あと試してみましたが、セッションに特にアクセスしていなくともクッキーは発行されているようですよ。
> ※ストレージは実際に格納されるまで確保されないとしても。そういわれて調べてみましたが、Global.asax に Session_Start ハンドラを追加すると、Session クッキーが発行されるのを確認しました。(これは今まで知らなかった新事実でした)
2 回目以降の要求で Session クッキーがブラウザからサーバーに送られるので、2 回目以降の要求は新しいセッションではないと判断されて、Session_Start イベントは発生しないというのがデフォルト(?)の動きになるようです。
ちなみに、Session_Start ハンドラを追加しただけで、Session State には明示的に何も保存しない場合(Session["Data"] = xxxx; のようなコードがない場合)でも、空の Session State がストレージに保存されるそうです。
> 同一ページを連続でリクエストしてみると、手元ではそれぞれ別のセッションIDで新しくセッションが
> 開始されているようです。それは具体的にどのようにリクエストして、どのように確認されたのでしょうか?
最初の要求で Session クッキーが発行されれば、2 回目以降の要求では Session クッキーがサーバーに送られるので、セッション ID は最初の要求と同じになると思いますが。
- 回答としてマーク NASASAN 2014年7月24日 4:52
-
> 上記のお話ですと、①の際、2画面目以降のセッションは本来、新規であるにも関わらず、
> ブラウザ側でCookie保持したセッションIDをサーバに送信してしまうために、
> サーバ側がそのセッションIDを取り込んで同一セッションとして扱ってしまうということでしょうか。ブラウザは何を使っているのですか?
IE8 以降ですと別画面でも同一セッション(同じクッキーを送出する)のがデフォルトの動作と言うことはご存知でしょうか?
なお、サーバーで SessionID プロパティで見た ID が、クッキーとしてブラウザに送信されて、2 回目以降の要求ではブラウザからサーバーにそのクッキーが送られるというのが前提です。(なので、先のレスで「HTTP ヘッダーを見たのでしょうか?」と聞きました)
IE8 のプロセスモデルについて
http://blogs.technet.com/b/jpieblog/archive/2010/05/10/3331472.aspx- 編集済み SurferOnWww 2014年7月24日 4:04 参考ページURL追記
- 回答としてマーク NASASAN 2014年7月24日 4:51
-
仕様か不具合かはMSに問い合わせてみないと分かりませんが、まず不具合ではなく仕様の可能性が高いでしょう。
そのようなリクエストをするのが間違い(あるいはその場合のこの動作は仕様通り)、ということになる可能性の方が高いです。
※そもそも、理屈的にこの動作は間違いというものではなく、仕様としてどうにでも決められるものです。
もちろん、同じセッションIDなら、セッション作成途中でもロックをかけて同一セッションとみなす、という仕様もあり得たでしょうし、ASP.NETではたまたま現在の動作を仕様とした、ということにすぎないでしょう、おそらく。
※不具合の原因の報告を求められているなどだとは思いますが、ASP.NETの不具合という方向は筋が悪そうに思います。
どうしても確認したければ、MSに問い合わせるしかないでしょう。
- 回答としてマーク NASASAN 2014年7月24日 6:02
すべての返信
-
説明上、仮にセッションIDを[AAAA]としますが、
2画面連続で開いた際にセッションIDは2つの画面ともにSession_Startでログ出力すると[AAAA]となっています。
これ自体は問題ではありませんが、2画面目のIsNewSessionがtrueになってしまいますため、
★の箇所でリターンせずにその後の処理が実行されます。
ちなみに本事象が発生する2画面連続で開く間隔はごく短時間の場合のみで、ある程度(大体1秒)空ければ
本事象は発生いたしません。(つまり2画面目は★でリターンします)
--------------------------------------------------
ASP_APP Global.aspx.cs
--------------------------------------------------void Session_Start(object sender, EventArgs e)
{
if (!Session.IsNewSession)
return; // ★2画面目はここでリターンすると想定していました。セッションIDは[AAAA]// 以降、固有処理
// 1画面目はここまで処理される。セッションIDは[AAAA]
// 2画面目もここまで処理される。セッションIDは[AAAA]
}
-
SessionState 情報を格納しない場合(Session["Data"] = xxxx; というようなコードが存在しない場合)、サーバーは SessionState 情報用のストレージを割り当てません。また、セッション Cookie も発行しません。
SessionID は HttpSessionModule が生成しますが、Cookie が送られてこなければ HttpSessionModule が生成する SessionID の値はリクエストのたび異なります。
そういう理由ではないのでしょうか?
セッションIDが同じだということですから、そういうことではないでしょう。
あと試してみましたが、セッションに特にアクセスしていなくともクッキーは発行されているようですよ。
※ストレージは実際に格納されるまで確保されないとしても。ASP.NET4の開発Webサーバでの動作ですが。
同一ページを連続でリクエストしてみると、手元ではそれぞれ別のセッションIDで新しくセッションが開始されているようです。
※これはまあ、理屈上は納得できる動作です。
もちろん、クッキーは後のレスポンスで上書きされますので、最初のセッションは捨てられることになりますが。気になるとしたら、Session_StartでIsNewSessionのチェックとその他の処理を行っていますが、Session_Startはセッション開始イベントなのですから、常に新しいセッションなのは当たり前に思えます。
※どちらかというと、何故2画面目でSession_Startが起こっているのか、という問題ですね。
ありそうなのは、セッションは開始されていないが、すでに発行されたセッションクッキーをブラウザが保持している状態の場合です。
この場合、サーバ側ではセッションは新規開始ですが、セッションIDはクッキーのIDになります。
よって、書かれている現象のようなことが起こると思われます。
※実際試してみたら再現しました。
セッション開始は、上記のように同時に複数リクエストがあると正常に動作しませんので、元の画面側で開始しておくなど、何らかの対処が必要です。
しかし、同一セッションのリクエストは、読み取り専用のセッションでないと同時処理できない仕様になっていますので、ちょっと作りから考え直す必要があるかもしれません。
-
なちゃさん 回答ありがとうございます。
私がログ出力して確認した際、セッションIDは以下のようになっていました。
①同一PC、単一プロセスからの複数画面起動 ・・・全て同じセッションID
②同一PC、複数プロセスからの複数画面起動 ・・・全て別のセッションID
③複数PC ・・・全て別のセッションID
上記のお話ですと、①の際、2画面目以降のセッションは本来、新規であるにも関わらず、
ブラウザ側でCookie保持したセッションIDをサーバに送信してしまうために、
サーバ側がそのセッションIDを取り込んで同一セッションとして扱ってしまうということでしょうか。
本動作は、ステートレスなHTTPプロトコルに対してセッション管理するためのASP.NET元来の仕組みであり、
致し方ないというより、そうあるべきのような気がしています。
元々の話ですが、上記の際に、
.NET Frameworkの動作としては、IsNewSessionは「false」になるべきではないのでしょうか。
技術的に理解が未熟であり勘違い発言しているかもしれません…。
-
> あと試してみましたが、セッションに特にアクセスしていなくともクッキーは発行されているようですよ。
> ※ストレージは実際に格納されるまで確保されないとしても。そういわれて調べてみましたが、Global.asax に Session_Start ハンドラを追加すると、Session クッキーが発行されるのを確認しました。(これは今まで知らなかった新事実でした)
2 回目以降の要求で Session クッキーがブラウザからサーバーに送られるので、2 回目以降の要求は新しいセッションではないと判断されて、Session_Start イベントは発生しないというのがデフォルト(?)の動きになるようです。
ちなみに、Session_Start ハンドラを追加しただけで、Session State には明示的に何も保存しない場合(Session["Data"] = xxxx; のようなコードがない場合)でも、空の Session State がストレージに保存されるそうです。
> 同一ページを連続でリクエストしてみると、手元ではそれぞれ別のセッションIDで新しくセッションが
> 開始されているようです。それは具体的にどのようにリクエストして、どのように確認されたのでしょうか?
最初の要求で Session クッキーが発行されれば、2 回目以降の要求では Session クッキーがサーバーに送られるので、セッション ID は最初の要求と同じになると思いますが。
- 回答としてマーク NASASAN 2014年7月24日 4:52
-
> 上記のお話ですと、①の際、2画面目以降のセッションは本来、新規であるにも関わらず、
> ブラウザ側でCookie保持したセッションIDをサーバに送信してしまうために、
> サーバ側がそのセッションIDを取り込んで同一セッションとして扱ってしまうということでしょうか。ブラウザは何を使っているのですか?
IE8 以降ですと別画面でも同一セッション(同じクッキーを送出する)のがデフォルトの動作と言うことはご存知でしょうか?
なお、サーバーで SessionID プロパティで見た ID が、クッキーとしてブラウザに送信されて、2 回目以降の要求ではブラウザからサーバーにそのクッキーが送られるというのが前提です。(なので、先のレスで「HTTP ヘッダーを見たのでしょうか?」と聞きました)
IE8 のプロセスモデルについて
http://blogs.technet.com/b/jpieblog/archive/2010/05/10/3331472.aspx- 編集済み SurferOnWww 2014年7月24日 4:04 参考ページURL追記
- 回答としてマーク NASASAN 2014年7月24日 4:51
-
> あと試してみましたが、セッションに特にアクセスしていなくともクッキーは発行されているようですよ。
> ※ストレージは実際に格納されるまで確保されないとしても。そういわれて調べてみましたが、Global.asax に Session_Start ハンドラを追加すると、Session クッキーが発行されるのを確認しました。(これは今まで知らなかった新事実でした)
ああ、そういうことですか。
確かにデフォルトで生成されたSession_Startハンドラがあるので、その条件ということですね、なるほど。
> 同一ページを連続でリクエストしてみると、手元ではそれぞれ別のセッションIDで新しくセッションが
> 開始されているようです。それは具体的にどのようにリクエストして、どのように確認されたのでしょうか?
最初の要求で Session クッキーが発行されれば、2 回目以降の要求では Session クッキーがサーバーに送られるので、セッション ID は最初の要求と同じになると思いますが。
今回の動作の確認のためにやったことですので、上述の連続リクエストというのは、同時リクエストの意味あいです。
スリープを入れた時間のかかるページを用意して、同時処理されるようにブラウザから別タブで連続にリクエストを投げたということです。
セッションの確認は、ページに表示したセッションIDやIsNewSessionの値と、リクエストおよびレスポンスのクッキーヘッダの状態ですね。
- 編集済み なちゃ 2014年7月24日 4:42
-
>ブラウザは何を使っているのですか?
IE8です。
>IE8 以降ですと別画面でも同一セッション(同じクッキーを送出する)のがデフォルトの動作と言うことはご存知でしょうか?
いえ。承知しておりませんでしたが、
上記で検証した通り、ASP.NET画面を開く元画面が単一であった場合には、
複数画面を開いても全て同一セッションでした。
本動作(上記の①)は、ご指摘の内容に一致するものと認識しています。
しかしながら、SurferOnWwwさんのご指摘は、上記の②もIE8のデフォルト動作と異なっているということですかね。
>なお、サーバーで SessionID プロパティで見た ID が、クッキーとしてブラウザに送信されて、2 回目以降の要求ではブラウザからサーバ>ーにそのクッキーが送られるというのが前提です。(なので、先のレスで「HTTP ヘッダーを見たのでしょうか?」と聞きました)
すみません。HTTPヘッダ調査はこれからですが、
お2人から頂戴した回答を総合判断しますと、
以下のようになるのでしょうか。おそらく2画面目を開いた際、同一セッションIDをサーバに送信しているが、
Session_Startが呼ばれる=サーバ側としては新しいセッションとして判別している。(IsNewSessionは「true」)
しかし、1画面目と同一セッションIDを受け取っているため、その後は同一セッションとして扱っている。 -
今回の問題では、まだセッションが開始されていない状態で(ただしセッションクッキーは何らかの事情で残っている状態で)、2つのリクエストを同時に発行したため、各リクエストで新規セッションの開始処理がされてしまったという動作です。
ASP.NET的には上記のような同時リクエストは想定外なのでしょう。
いったんセッションが作成された後は、同一セッションのリクエストは、先に開始されたリクエストが終了するまで、次のリクエストは待機させられます。つまり、同時にリクエストを処理することはできません。
これは、セッションストアへの読み書きをシリアライズするための動作です。
※ASP.NETではセッションストアからの読み出しと保存は、リクエストの開始と終了のタイミングでまとめて行われます。
セッション変数へのアクセスの都度実行されるわけではありません。
セッションの保存場所は、ステートサーバやDBだったりすることもあるので、このような動作が必要になるわけです。読み取り専用のセッションとは、まあ調べてもらえればわかりますが、セッション変数の読み出しだけを行い、書き込みは行わないセッションへのアクセスの仕方です。
セッションの読み取りしかしないページでは、書き込みのためのロックを必要としませんので、読み取り専用のアクセスしかしないページ同士であれば、同時にリクエストを処理できるということです。
セッションが読み取り専用かどうかは、Pageディレクティブで指定します。
-
HTTPヘッダを調べましたが、
やはり1画面目と同一セッションIDを送信していました。
>今回の問題では、まだセッションが開始されていない状態で(ただしセッションクッキーは何らかの事情で残っている状態で)、2つのリクエストを>同時に発行したため、各リクエストで新規セッションの開始処理がされてしまったという動作です。
>ASP.NET的には上記のような同時リクエストは想定外なのでしょう。>いったんセッションが作成された後は、同一セッションのリクエストは、先に開始されたリクエストが終了するまで、次のリクエストは待機させら>れます。つまり、同時にリクエストを処理することはできません。
>これは、セッションストアへの読み書きをシリアライズするための動作です。
云い方とは思いますが、ASP.NET想定外=不具合と考えても良いのでしょうか。
実は、今回の事象に際して、現時点ではソフト改修が目的ではなく
本事象自体がASP.NETの不具合か否か見極めることにあります。
>※ASP.NETではセッションストアからの読み出しと保存は、リクエストの開始と終了のタイミングでまとめて行われます。
> セッション変数へのアクセスの都度実行されるわけではありません。
> セッションの保存場所は、ステートサーバやDBだったりすることもあるので、このような動作が必要になるわけです。まとめて・・・。こちらは全く存じ上げませんでした。
勉強になります。
>読み取り専用のセッションとは、まあ調べてもらえればわかりますが、セッション変数の読み出しだけを行い、書き込みは行わないセッションへ>のアクセスの仕方です。
>セッションの読み取りしかしないページでは、書き込みのためのロックを必要としませんので、読み取り専用のアクセスしかしないページ同士で>あれば、同時にリクエストを処理できるということです。
>セッションが読み取り専用かどうかは、Pageディレクティブで指定します。
成程ですね。
ご教示ありがとうございます。
-
仕様か不具合かはMSに問い合わせてみないと分かりませんが、まず不具合ではなく仕様の可能性が高いでしょう。
そのようなリクエストをするのが間違い(あるいはその場合のこの動作は仕様通り)、ということになる可能性の方が高いです。
※そもそも、理屈的にこの動作は間違いというものではなく、仕様としてどうにでも決められるものです。
もちろん、同じセッションIDなら、セッション作成途中でもロックをかけて同一セッションとみなす、という仕様もあり得たでしょうし、ASP.NETではたまたま現在の動作を仕様とした、ということにすぎないでしょう、おそらく。
※不具合の原因の報告を求められているなどだとは思いますが、ASP.NETの不具合という方向は筋が悪そうに思います。
どうしても確認したければ、MSに問い合わせるしかないでしょう。
- 回答としてマーク NASASAN 2014年7月24日 6:02