Shizuku Blog ~ techbank.jp版~

~女性エンジニア けろ-みおの苦悩~

ログイン | ID登録 | ヘルプ


ニュース


当Blogにについて

当Blogは、けろ-みおが備忘録として活用しているBlogになります。掲載している内容について、必ずしも正しい情報を公開しているわけではありませんので予めご了承下さい。
当Blogで公開している記事に対して、質問がある場合は、techbank.jp掲示板でお問い合わせ頂くか、techbank.jp ID申請を行い、IDを作成した段階で当Blogにコメントする等してください。
原則、正体がわからない方からのBlogコメント欄を使ったご質問・ご指摘は、承っておりません。
コメント投稿・公開(承認)基準につきましては、 当Blogのコメント投稿についてをご確認ください。
テクニカルコミュニティ(techbank.jp)に設置しているBlogということもあり、皆様のご理解とご協力の程、宜しくお願いします。

自己紹介

けろ-みおと申します。「techbank.jp」の副管理人をやっております。

MVP Profile

0







けろ-みおの関連サイト





このBlogの人気度
フィードメーター - techbank.jpコミュニティ

techbank.jp Blog全体と近いBlog
あわせて読みたいブログパーツ

このBlogと近いBlog
あわせて読みたいブログパーツ

Blog購読者数
スカウター : techbank.jp







[ASP.NET] : IHttpModule で管理クラス外からのSession保存禁止する方法

 

 

※この記事はかつて、わんくまBlogで書いていたものです。こちらに移行します

 

この記事は、Sessionの管理ってどうやるんでしょう?というための記事です。

 

IHttpModuleを使って、SessionをFilterし、管理クラス外から追加されたSessionの場合は、例外を生成するようにしてみました。

今回はわかりやすくしている都合上、例外を生成してますが、一番いいのは、管理クラス外で生成&追加されたSessionの場合は、

Sessionを削除(Remove)してしまうのが、本来のやり方かなと思います。

(本当は、SessionModuleをオリジナルで作るというものにしたかったんですが、やめました。

 また機会があればSessionModuleで実験します)

 

また、無許可ですが、むらさんのところにあったSessionContainerクラスとSessionManagerクラスを一部改造しました。

(以前、むらさんから改造について、ご了承頂いたので、今は問題なしです。)

 

 

■Web.config

<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
    <httpModules>
    <!-- 本当はSessionModuleにしたかったので、Remove定義してましたが、今回は見送ったのでコメント(.NET標準のを使う) -->
    <!--<remove name="Session" />-->
    <add type="Kero.CustomSessionStateModule" name="test" />
    </httpModules>
</system.web>
</configuration>

 

■SessionContainer.vb

Namespace Kero
 
    'セッションコンテナ
    Public Class SessionContainer
       
        Private _Object As Object
        Private _Expire As Date = DateTime.MaxValue
 
        Public Sub New()
 
        End Sub
 
        Public Sub New(ByVal [object] As Object, ByVal expire As Date)
            _Object = [object]
            _Expire = [expire]
        End Sub
 
        '格納するオブジェクト
        Public Property [Object]() As Object
            Get
                Return _Object
            End Get
            Set(ByVal value As Object)
                _Object = value
            End Set
        End Property
 
        'セッションの保持期間
        Public Property Expire() As Date
            Get
                Return _Expire
            End Get
            Set(ByVal value As Date)
                _Expire = value
            End Set
        End Property
 
    End Class
 
End Namespace
 

 

■SessionManager.vb

Namespace Kero
 
    Public Class SessionManager
 
        'セッションに格納(有効期限自動設定)
        Public Shared Sub Add(ByVal page As System.Web.UI.Page, _
                                     ByVal key As String, _
                                     ByVal [object] As Object)
 
            page.Session.Add(key, New SessionContainer([object], DateTime.Now.AddMinutes(10)))
 
        End Sub
 
        ' セッション格納(有効期限指定)
        Public Shared Sub Add(ByVal page As System.Web.UI.Page, _
                              ByVal key As String, _
                              ByVal [object] As Object, _
                              ByVal [expire] As Date)
 
            'コンテナをセッションに追加
            page.Session.Add(key, New SessionContainer([object], [expire]))
 
        End Sub
 
        'セッション取得
        Public Shared Function [Get]( _
                           ByVal session As System.Web.SessionState.HttpSessionState, _
                           ByVal key As String) As Object
 
 
          'セッションを探す
            Dim sc As SessionContainer = TryCast(session.Item(key), SessionContainer)
 
 
          '取得できたら(かつSessionContainerに入っていたら)返す
            If sc IsNot Nothing Then Return sc.Object
 
 
          '取得できなければ何も返さない
            Return Nothing
 
 
        End Function
 
 
       'セッション初期化
        Public Shared Sub InitializeSession(ByVal page As System.Web.UI.Page)
           
            For i As Integer = page.Session.Keys.Count - 1 To 0 Step -1
 
                Dim name As String = page.Session.Keys(i)
 
                If TypeOf (page.Session(name)) Is SessionContainer Then
 
                    ' 有効期限切れSessionは削除
                       Dim sc As SessionContainer
                    sc = CType(page.Session.Item(name), SessionContainer)
 
                    If sc.Expire <= DateTime.Now Then
 
                        page.Session.Remove(name)
 
                    End If
 
 
                End If
 
 
            Next
 
 
        End Sub
 
 
       'セッション情報削除
        Public Shared Sub Remove(ByRef page As System.Web.UI.Page, _
                                           ByVal key As String)
 
 
            'セッションに存在する場合、削除
            If page.Session.Item(key) IsNot Nothing Then
                page.Session.Remove(key)
            End If
 
        End Sub
 
    End Class
 
End Namespace
 

 

■CustomSessionStateModule.vb

Imports System
Imports System.Web
Imports System.Web.SessionState
Imports System.Collections
Imports System.Threading
Imports System.Web.Configuration
Imports System.Configuration
Namespace Kero
    Public Class CustomSessionStateModule
        Implements IHttpModule
 
        Public Sub Dispose() Implements System.Web.IHttpModule.Dispose
       
        End Sub
 
        Public Sub Init(ByVal httpApplication As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
 
            ' Webページの実行完了時イベントの登録
            AddHandler httpApplication.PostRequestHandlerExecute, AddressOf CustomStateFilter
 
        End Sub
 
        ' Webページの実行完了時イベント
        Public Sub CustomStateFilter(ByVal sender As Object, ByVal e As EventArgs)
 
            Dim app As HttpApplication = CType(sender, HttpApplication)
            Dim context As HttpContext = app.Context
 
            If context.Session Is Nothing Then
                Return
            End If
 
            Try
            
                For Each sessionKey As String In context.Session
 
                    Dim sessionContainer As SessionContainer = TryCast(context.Session.Item(sessionKey), Kero.SessionContainer)
 
                    If sessionContainer Is Nothing Then
 
                        Throw New ApplicationException("管理クラス以外からのセッション操作は禁じられています")
 
                    ElseIf sessionContainer.Expire <> DateTime.MaxValue AndAlso sessionContainer.Expire <= DateTime.Now Then
 
                        Throw New ApplicationException("有効期限が過ぎているセッションが保存されました")
 
                    End If
 
                Next
 
            Catch ex As Exception
            
                Throw ex
                
            End Try
            
        End Sub
 
    End Class
End Namespace
 

 

 

■テスト用Webページ(Default.aspx.vb)

Partial Class _Default
    Inherits System.Web.UI.Page
 
    Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
 
#If 1 Then
        ' これはNG
        Context.Session("test") = "Hello World"
#Else
        ' これはOK
        Kero.SessionManager.Add(Me.Page, "kero", "Hello World", DateTime.Now.AddMinutes(10))
#End If
   
    End Sub
 
End Class
 

 

 

■実行結果

 

 

■まとめ

やっぱりSessionを管理するというのは、いろんな方法や縛りをつけることはできますが、いろいろと面倒で厄介。

また、Session禁止!といっても、そうはいかない部分もあります。

Sessionの追加と削除が行える管理クラスを用意するのが、手っ取り早い対応策ですね。

Session保存先をDBにして、貯めるだけ貯めて、後で一括削除っていうのもありなんですが、

そうすると有効期限でSessionを消したいとかレスポンスを求められている場合などは、ちょっと苦しいですね。

(レスポンスは意識せず、大量データをSessionに保存する場合は、保存先をDBにするのが向いてます)

ご参考になれば幸いです。

Published 2008年4月13日 23:51 けろ-みお

コメント

このBlogに対するコメントはありません

コメントを残す

(必須) 
(必須) 
(オプション)
(必須)