書籍転載
独習ASP.NET 第3版

ASP.NETの状態管理:ビューステート/クッキー/セッション情報
― 第7章 状態管理 7.1/7.2/7.3 ―

WINGSプロジェクト 山田 祥寛
2011/07/20
Page1 Page2 Page3

7.3 セッション情報

 前節では、ページ間で情報を共有するための仕掛けとして、クッキーを取り上げました。しかし、クッキーにはいくつかの問題点があります。

[問題]データがクライアント側で保存される

 前節でも述べたように、クッキーはクライアント側で管理されるデータです。クライアント(ブラウザー)の設定によってはそもそもクッキーを受け入れないようにすることも可能ですし、いったん保存されたクッキーをクライアント側で改ざんしたり削除したりすることもできます。そのため、クッキーによって得られたデータをもとに処理を制御するのは、時として危険が伴う場合があります。

[問題]実データがネットワーク上を流れる

 図7.5でも見たように、クッキーはネットワーク上で受け渡しされます。つまり、通信経路にリクエスト情報をロギングするような通信機器やソフトウェアがあったとしたら、意図するとせざるとにかかわらず、クッキーの内容が漏えい(盗聴)されてしまう可能性があります。

 セキュリティが取りざたされる昨今の情勢を考えれば、このような状態はセキュリティホールの一因となる場合もあり、好ましいことではありません。そこで、ユーザーがブラウザーを開いている間だけ情報を維持したいという場合には、クッキーではなく、セッション(Session)という仕組みを利用するようにすべきです。セッションは、何日、何週間という単位で情報を保持するような用途には不向きですが、アプリケーション内で情報を受け渡ししたいという場合には、クッキーよりも手軽に、かつ、セキュアに扱うことができます。

7.3.1 セッション機能の基本

 まずはセッションの仕組みについて見てみることにしましょう(図7.8)。

図7.8 クッキーとセッション

 まず理解していただきたいのは、セッション情報そのものはあくまでサーバーサイドで管理されるものであり、クライアント/サーバー間でやりとりされるのは、そのキーだけであるという点です。そして、クライアント単位に発行されるキーとなるのが、セッションIDです。サーバーサイドでは、クライアントから発信されたセッションIDをキーにして、セッション情報にアクセスできます。

 これによって、セッションでは「データがユーザーに改ざん/削除されてしまう」「データを盗聴されやすい」という、クッキーの問題点を解消しているのです。

 セッション情報の取得/設定は、クッキーよりも簡単です(リスト7.4〜5)。

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  Session("title") = "独習ASP.NET"
End Sub
リスト7.4 Session1.aspx.vb

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  If Session("title") IsNot Nothing Then
    lblSession.Text = Session("title")
  End If
End Sub
リスト7.5 Session2.aspx.vb

 Session1.aspxを実行した後、ブラウザーを閉じずにそのままSession2.aspxにアクセスしてください。確かにSession1.aspxでセットされたアプリケーション変数が、Session2.aspxでも見えていることが確認できるはずです。クッキーとは異なり、セッションはあくまでブラウザーが開いている間のみ情報を保持するための機能なので、ブラウザーを閉じてしまうと、セッションもクリアされます。

 セッションを読み書きするのは、Sessionオブジェクトの役割です。

Session(キー名) [=値]
構文 セッションの取得/設定

 取得に際しては、値がまだセットされていない場合も想定して、必ずNothingであるかどうかのチェックを忘れないようにしてください。

 また、既存のセッションを削除するには、Remove/RemoveAll/Abandonメソッドを利用します。Removeメソッドは指定された特定のセッション情報を、RemoveAllメソッドは現在保持されているセッション情報すべてを、そして、Abandonメソッドは、セッションそのもの(情報だけではなく、セッション情報のキーであるセッションIDを含む)を破棄します。

Session.Remove("hogehoge") 'セッション情報"hogehoge"を削除

Session.RemoveAll() 'すべてのセッション情報を削除

Session.Abandon() 'セッションそのものを削除

 前述したように、セッション情報はサーバー上に保持されるものです。サーバー上のリソースを節約するという意味からも、セッション情報は、不要になったできるだけ早いタイミングで破棄すべきでしょう。

【エキスパートに訊く】
セキュリティ保全のためにはセッション機能を利用するべきであるということでした。でも、セッションを使えばセキュリティは絶対に安全なのでしょうか?

 いえ、そのようなことはありません。セッションでも、セキュリティIDがネットワーク上を流れる以上、これを盗聴されてしまえば、いわゆる「なりすまし」も可能です。しかし、そもそもセッションID自体が一時的に生成されるキーですので、リアルタイムで盗聴を行っていない限り、なりすましを行うのは難しいと言えます。

 ここでセッションが安全と言っているのは、あくまで「データが直接ネットワーク上を行き来するクッキーよりも相対的に」という程度の意味です。

7.3.2 <sessionState>要素の主な属性

 セッションの基本的な仕組み、利用方法が理解できたところで、セッションの保存/授受方法など基本的な設定をアプリケーション構成ファイル上でカスタマイズする方法について紹介しましょう。セッションの挙動を表すのは、<sessionState>要素の役割です。

 以下に、sessionState要素で利用できる主な属性をまとめます。

mode属性

 セッションの格納先を設定します。表7.5のような値を設定できます。

設定値 概要
Off セッションが無効
InProc ローカルのメモリ上に格納
StateServer 専用のState Serviceに格納
SQLServer SQL Serverに格納
Custom カスタムのデータストアに格納
表7.5 mode属性の設定値

 InProc(インプロセスモード)は、サーバーのメモリにセッションを保存するモードで、最も高速に動作します。しかし、サーバーをクラスター構成にした場合、セッションを共有できない、アプリケーションの再起動時にセッションがクリアされてしまう、などの制約もあります。

 本番環境でセッションを利用する場合には、State Server、SQL Serverなどのモードを優先して利用することをおすすめします。これらのモードは、インプロセスモードよりも低速ですが、その分、確実にセッションを維持できます。

* Webアプリケーションの再起動は次のような場合に発生します。
  • Global.asaxやWeb.configが変更された
  • あらかじめ設定されたリサイクル時間が経過した
  • サーバーメモリが大量に消費された
  • アプリケーション配下のBinフォルダーが変更された
ウィルス駆除ソフトを利用している場合には、Global.asaxやWeb.configのスキャンによってファイルが変更されたと見なされてしまうこともあります。ASP.NETでは、アプリケーションの再起動はごく当たり前に行われていると考えたほうが良いでしょう。

timeout属性

 セッションのタイムアウト時間(デフォルトは20分)を設定します。

 パフォーマンス、セキュリティ双方の側面から、timeout属性にはアプリケーションごとに適切な値を設定すべきです。不要になったセッションがサーバー上に残り続けることは、サーバーリソースの浪費だけでなく、悪意ある第三者(クラッカー)に対してセッション盗聴の機会を与えることでもあるからです。

 ただ、無条件にタイムアウト時間を短くしてやればそれで良いというものではありません。ユーザーが長時間に渡って放置する可能性があるグループウェアのようなアプリケーションでは、長めにタイムアウト時間を確保する必要があるかもしれませんし、厳密なセキュリティを要求されるアプリケーションでは短めに設定すべきです。大量のセッションデータを保持するようなアプリケーションやメモリリソースが逼迫しているようなサーバー環境でもタイムアウト時間を短めに設定してやらなければならないかもしれません。タイムアウト時間とは、その時どきの用途/環境の制約に応じて「あなたが」チューニングすべき項目です。

* セッションの性質上、やや誤解を招きやすいのですが、セッション情報はブラウザーを閉じた時点ではまだ破棄されていません。ブラウザーを閉じた時点で削除されるのは、セッション情報を紐づけるためにブラウザーに保存されたセッションIDだけであり、これによって、クライアント側からは見かけ上、セッションが破棄されたように見えるわけです。しかし、サーバー側で保持されたセッション情報は、この時点では依然として生き続けています。サーバー側のセッション情報を破棄するには、Abandonなどのメソッドを明示的に呼び出すか、セッションの有効期限を経過しなければなりません。

commpressionEnabled属性

 セッション情報を圧縮します。特に、セッション情報を外部プロセスに保存する場合には、圧縮機能を有効にし、データサイズを最小限に抑えることをおすすめします。ASP.NET 4から導入された新機能です。

cookieless属性

 セッションIDをクッキー、URL埋め込みのいずれで受け渡すかを設定します(表7.6)。

設定値 概要
AutoDetect ブラウザーのクッキーサポート、有効無効をチェックし、その結果によってクッキー、URL埋め込みのいずれかを選択的に利用
UseCookies 常にクッキーを使用
UseDeviceProfile ブラウザーのプロファイル情報によってクッキー、URL埋め込みのいずれかを選択的に決定
UseUri 無条件にクエリ文字列を使用
表7.6 cookieless属性の設定値

 AutoDetect/UseDeviceProfileモードでは、ブラウザーがクッキーをサポートしていない場合にURL経由でセッションIDを受け渡ししようとします。これには、以下のようなURLが用いられます。

http://localhost:81/(S(m0i5pggddoymmw0sbnqcybce))/Chap07/Session1.aspx

 しかし、これはセッションIDがまるまる露出してしまうという点で、セキュリティ的には好ましくありません(クッキーであれば絶対に安全という意味ではありません)。クッキーレス対応は、クッキー未対応のブラウザーでセッションを利用する場合に留めるようにしてください。そうした意味で、UseUriモードはテスト目的の場合を除いては利用するべきではありません。

* そもそもAJAX対応のアプリケーションを実装している場合、URL埋め込みのセッションは利用できません。

7.3.3 セッションの外部プロセス管理

 パフォーマンス上のデメリットこそあるものの、外部プロセスでセッションを管理することで、セッション情報をより確実に維持できるというメリットがあります。本番環境でのセッション管理には、できるだけ外部プロセスによる管理を選択することをおすすめします。

 以下では、外部プロセス管理の1つとして、State Service(ASP.NET状態サービス)によるセッション管理の方法を解説します。インプロセスモードと同じく、メモリ上でセッション情報を管理しますが、アプリケーションとは別のプロセス(サービス)で動作するという点が異なります。後述するSQL Serverモードよりは高速ですが、State Serviceを再起動すると、やはりセッション情報は破棄されてしまいますので、注意してください。

1.State Serviceを起動する

 State Serviceは、コントロールパネルの[システムとセキュリティ]→[管理ツール]→[サービス]から起動できます。[ASP.NET状態サービス]を右クリックし、コンテキストメニューから[開始]を選択します(図7.9)。

図7.9 State Serviceの起動

* プロパティシートから[スタートアップの種類]を[自動]とすることで、サーバー起動時に自動起動させることもできます。

2.State Serviceを有効化する

 State Serviceによるセッション管理を有効にするには、アプリケーション構成ファイルにリスト7.6のような記述を追加します(記述位置は<system.web>要素の直下であればどこでもかまいません)。

<system.web>
  ……中略……
  <sessionState mode="StateServer"
                stateConnectionString="tcpip=127.0.0.1:42424" />
  ……中略……
</system.web>
リスト7.6 Web.config

 以上でState Serviceを使用する設定は完了です。これで、セッションデータはState Serviceのプロセス上に保存されるようになりました。<sessionState>要素のstateConnectionString属性には、今回はローカルアドレス(127.0.0.1)を指定していますが、一般的にはState Serviceが稼働しているサーバーのIPアドレスを指定します。

7.3.4 セッションのSQL Server管理

 ただし、State Serviceでも、セッション情報はメモリに保存されます。つまり、サーバーの再起動によって、セッションがクリアされてしまう点は、インプロセスモードと変わりありません(アプリケーションと分離されている分、安全というだけです)。セッション情報をより確実に維持するという意味では、SQL Serverモードを利用するのが望ましいでしょう。

1.SQL Serverにセッションデータベースを生成する

 SQL Serverをセッションの保存先として使用する場合には、あらかじめ.NET Frameworkのインストールフォルダーに用意されたaspnet_regsqlを利用して、セッション管理用のデータベースをSQL Serverに展開しておく必要があります。

 aspnet_regsqlは「<システムルート>¥Microsoft.NET¥Framework¥<バージョン番号>」に保存されていますので、コマンドプロンプトから以下のように実行してください。

> cd C:\Windows\Microsoft.NET\Framework\v4.0.30319
> aspnet_regsql -S .\SQLEXPRESS -E -ssadd -sstype p

 それぞれのオプションの意味は、表7.7のとおりです。

オプション 概要
-S server 接続先のSQL Serverのコンピューター名
-EWindows 認証を有効化
-ssadd セッションデータベースを作成
-sstype type 作成するデータベースの種類
表7.7 aspnet_regsqlコマンドの実行オプション

 -sstypeオプションには、セッションデータベースを永続的なデータベース(p:ASPStateデータベース)に作成するか、一時的なデータベース(t:tempdbデータベース)に作成するかを指定します。ただし、tempdbデータベースではSQL Serverを再起動するたびに、セッション情報はクリアされてしまいますので、要注意です。

2.セッションデータベースを確認する

 VWDのデータベースエクスプローラー(サーバーエクスプローラー)からデータベースの内容を確認しておきましょう。[データ接続]を右クリックし、コンテキストメニューから[接続の追加...]を選択します(図7.10)。

図7.10 ASPStateデータベースへの接続設定

 セッション格納/操作のためのテーブルやストアドプロシージャが、ASPStateデータベースに作成できていることが確認できます(図7.11)。ASPStateTempApplicationsテーブルは現在「SQL Serverセッション」を利用しているアプリケーションを、ASPStateTempSessionsテーブルはセッションに関する一連の構成情報(ID、作成時間、有効期限、タイムアウト期限、データ本体)をそれぞれ格納するテーブルです。

図7.11 ASPStateデータベースの内容

3.SQL Serverを有効化する

 Web.configにリスト7.7のように記述します(記述位置は<system.web>要素の直下であればどこでもかまいません)。

<system.web>
  ……中略……
  <sessionState mode="SQLServer" sqlConnectionString="Data Source=(local)\SQLEXPRESS;Integrated Security=True" />
  ……中略……
</system.web>
リスト7.7 Web.config

 sqlConnectionString属性には、セッションデータベースに接続するための接続文字列を指定します。

 以上で、SQL Serverを使用する設定は完了です。これで、セッションデータはSQL Serverのテーブルに保存されるようになります。

* もしもそのページがセッション機能を必要としないならば、@Pageディレクティブでセッションを無効化、もしくは読み取り専用にすべきです。

<%@ Page EnableSessionState="False" %> ……無効
<%@ Page EnableSessionState="ReadOnly" %> ……読み取り専用

 セッションが外部プロセスに保存されている場合には、データアクセスを抑制できますので、ページのパフォーマンスを改善できます。

セッションが不要な場合

  アプリケーション全体でセッションを無効にする場合には、Web.configに<sessionState>要素を設定してください。


<sessionState mode="Off" />
Web.config

【練習問題】7.2
  1. クッキーの問題点をセッションと比較しながら説明してみましょう。
  2. セッションを破棄するための方法を、2つ挙げてみましょう。

 引き続き次回は、「第7章 状態管理」から「7.4 アプリケーション変数/7.5 キャッシュ機能」を転載します。end of article

 

 INDEX
  [書籍転載]独習ASP.NET 第3版
  ASP.NETの状態管理:ビューステート/クッキー/セッション情報
    1.ビューステート
    2.クッキー
  3.セッション情報

インデックス・ページヘ  「独習ASP.NET 第3版」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間