WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

Session_Start ハンドラの影響

by WebSurfer 2014年7月26日 17:03

Visual Studio 2010 のテンプレートを使って ASP.NET Web Forms アプリケーション(MVC ではなくて)を新規に作成すると、以下の画像のように、デフォルトで Global.asax ファイルの中に空の Session_Start ハンドラが生成されます。Session State を使わないのであれば、このコードは削除しておいた方がよさそうという話を書きます。

なお、以下の話で Session Cookie という言葉が出てきますが、ブラウザ / サーバー間のセッション ID の授受にクッキーを利用する(即ち、sessionState 要素 の cookieless 属性がデフォルトの UseCookies)ということが前提ですのでご注意ください。

Session_Start ハンドラ

つい先日、MSDN Forum でのやりとりを通じて、Global.asax に Session_Start ハンドラを追加するだけで、サーバーは Session State 情報用のストレージを割り当てて Session Cookie を発行することを知りました。

実は、明示的に Session Sate 情報を使用しない限り(即ち、 Session["Data"] = xxxx; のようなコードを書かない限り)Session Cookie が発行されることはないと思い込んでました。

自分では Session["Data"] = xxxx; のようなコードは書いた覚えはないのに、Fiddler2 などで HTTP ヘッダを見ると Session Cookie がやりとりされていたのが不思議だったのですが、Visual Studio が勝手に追加した Session_Start ハンドラが原因だと知ってやっと謎が解けました。(笑)

調べてみると、そのことは自分が持っている「プログラミング ASP.NET 4」という本の 17.3.1 章に書いてありました。せっかく 9,000 円も出して買った本なのに、読んでなかったです。(汗)

その本によると、"Session_Start ハンドラを使用する場合は、セッション状態は空であっても常に(セッション状態プロバイダーに)保存されます" とのことです。さらに、"Session_Start ハンドラはどうしても必要な場合にのみ細心の注意を払って定義してください" とも書いてありました。

というわけで、Visual Studio のテンプレートで自動生成される空の Session_Start ハンドラは、Session State を使わなければ、例え中身が空であってもアプリケーションに不要な負担をかけるだけなので、削除した方がよさそうです。

自分的には、Session Sate 情報を使用することはあっても、Session_Start ハンドラで何か処置を行う必要があるケースは考え付かないのです。なので、何故テンプレートでこのようなコードが自動的に追加されるのか謎です。


以下は余談ですが、今回の件で Session State に関して調べた情報を書いておきます。

サーバーに接続してくるクライアントごとに Session State をセットアップするのは、ASP.NET の既定の HTTP モジュール SessionStateModule です。

SessionStateModule は、クライアントからの要求を処置する HttpApplication オブジェクトのセットアップ時に呼び出され、一意な セッション ID 文字列の生成または取得と、セッション状態プロバイダ(Session State 情報のストレージ)に対するデータの格納と取得を請け負います。

セッションが開始される時、即ち、要求ヘッダに Session Cookie が含まれない状態でサーバーが初回の要求を受けると、SessionStateModule がセッション ID を生成します。

なお、2 回目の要求以降でも、ブラウザからの要求に Session Cookie が含まれてない場合は、SessionStateModule は要求のたびに新しいセッション ID を生成しますので注意してください。

ちなみに、セッション ID の文字列は、SessionID プロパティ から取得して調べることができます。ブラウザから Session Cookie が送られてこなければ、SessionID の値は要求のたび異なります。

Web アプリケーションの Global.asax に Session_Start ハンドラがあるか、Session State 情報を利用するコード(例えば、Session["Data"] = xxxx;)があると、サーバーは "ASP.NET_SessionId" という名前の Session Cookie を生成し、応答ヘッダに含めてブラウザに送信します。以下のような感じです。

Set-Cookie: ASP.NET_SessionId=d4rbf5nhk1xpo0qouuciwxgy; path=/; HttpOnly

上記の通り期限は設定されてないので、一旦クッキーを受け取るとブラウザを閉じない限りクッキーが消滅することはなく、ユーザーが同じドメイン内で閲覧するときには、ブラウザーはクッキーをサーバーに送信し続けます。

それはセッションがタイムアウト(sessionState 構成要素の timeout 属性に設定した時間が過ぎたことを意味します。デフォルトで 20 分)しても同じです。タイムアウトするとストレージに保存されていたセッションデータは破棄されますが、セッション ID は書き換えられず、同じ ID が使用され続けます。即ち、タイムアウトしてもブラウザとサーバ間のセッションは維持されます。

従って、2 回目以降の要求では毎回 Session Cookie がブラウザからサーバーに送られるので、それに含まれるセッション ID をベースにストレージからデータを取得するなどして HttpSessionState オブジェクトを生成することができます。HttpSessionState オブジェクトには Page の Session プロパティを通じてアクセスできます。

なお、2 回目以降の要求に Session Cookie が送られて来る場合は新しいセッションではないと判断され、Session_Start イベントは発生しないというのがデフォルトの動きになるようです。

なお、上にも書きましたが、Session_Start ハンドラがないもしくは Session State 情報を利用するコードがない場合は、サーバーからは Session Cookie は発行されず、上記とは異なった動きとなりますので注意してください。

以下は上にリンクを張った以外に参考にしたページの URL です。後で探さなくて済むよう貼っておきました。

Tags:

ASP.NET

セッションタイムアウトとログアウト

by WebSurfer 2013年6月29日 20:13

クラッシック ASP の場合は分かりませんが、ASP.NET の場合は、セッションの「タイムアウト」状態とフォーム認証の「ログアウト」状態��違います。

ASP.NET の場合「セッションタイムアウト」というと、MSDN ライブラリの セッション タイムアウトを構成する (IIS 7) によれば、sessionState 構成要素の timeout 属性に設定した時間が過ぎたことを言います。

セッションタイムアウトすると、サーバーに保存されていた SessionState 情報が破棄されます。しかし、それ以外の影響はありません。少なくともフォーム認証には無関係です。

また、SessionState 情報、SessionID、セッション Cookie のいずれからもフォーム認証のチケットに関する情報は取得できません。

なお、SessionState 情報を格納しない場合(Session["Data"] = xxxx; というようなコードが存在しない場合)、サーバーはセッション Cookie を発行しません。(2014/7/26 追記:Global.asax に Session_Start ハンドラを追加すると話が違ってきます。詳しくは、Session_Start ハンドラの影響 を参照ください)

SessionState 情報が格納される場合に限り、SeesionID を含むセッション Cookie が発行されます。なお、セッションタイムアウトしても SessionID は書き換えられず、同じ ID が使用され続けます。即ち、Session["Data"] に保存したデータは破棄されても、ブラウザは要求のたび同じセッション Cookie を送り続けます。

一方、フォーム認証の「ログアウト」状態とは認証チケットを持っていない、もしくは認証チケットは持っていても期限切れという状態です。セッションがタイムアウトしていても認証チケットは有効と言うことは当然あります。その逆もあります。

従って、フォーム認証チケットの有無もしくは期限切れと、セッションタイムアウトとは関係なく、セッションの「タイムアウト」状態 = フォーム認証の「ログアウト」状態にはならないです。

なお、Windows 認証、統合 Windows 認証は、フォーム認証とは全くメカニズムが異なっていて、セッションもクッキーも関係ないです。

Tags:

Authentication

HTTP ハンドラで Session を読み書き

by WebSurfer 2012年1月17日 22:27

HTTP ハンドラ内では Session の読み書きができません。例えば、以下のようにすると context.Session は null になって NullReferenceException がスローされてしまいます。

string s = (string)context.Session["note"];

ご存知でしたでしょうか? 実は、自分はそのことを知らなくて、つい先日 1 時間ぐらいハマってしまいました。(笑)

この問題を解決するには、HTTP ハンドラのクラスにマーカーインターフェースを継承させ、この HTTP ハンドラは Session へのアクセスを必要としているという印を付けてやります。

そのマーカーインターフェイスは System.Web.SessionState 名前空間 に属しており、以下のとおり 2 種類あります。

  1. IRequiresSessionState 読み取り/書き込みアクセス権を必要とすることを指定します。
  2. IReadOnlySessionState 読み取り専用アクセス権のみが必要であることを指定します。

実際の使用例は、まぁ、書かなくても分るとは思いますが、以下のような感じです(この例では IRequiresSessionState を使用)。

<%@ WebHandler Language="C#" Class="_MyHttpHandler" %>

using System;
using System.Web;
using System.Web.SessionState;

public class _MyHttpHandler : IHttpHandler, IRequiresSessionState 
{    
  public void ProcessRequest (HttpContext context) 
  {
    byte[] data = (byte[])context.Session["PageResponse"];
        
    if (data != null)
    {
      context.Response.BinaryWrite(data);
      context.Session.Remove("PageResponse");
    }
    context.Response.End();
  }
 
  // 以下省略

マーカーインターフェイスはメソッドの定義を持たないので、一般的なインターフェイスを継承したときのように、継承したクラス内にメソッドを実装する必要はありません。

Tags: ,

ASP.NET

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年4月  >>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar